/*
 * net_packet.c
 *
 *  Created on: 2023年7月22日
 *      Author: mcealt_DS
 */
#include "net_packet.h"
#include "RBFCommon.h"
#include "app_log.h"
#include "MacCrypto.h"
#include "net_addressing.h"
#include "net_rolling_code.h"
#include "net_protocol.h"
#include "net_aseq.h"
#include "net_msgseq.h"
#include "net_broadcast.h"
#include "net_qrf.h"
#include "net_logout.h"
#include "device.h"
#include "device_type.h"

#include "RBFCommissioning.h"
#include "RBFUpload.h"
#include "RBFDownload.h"
#include "RBFVersion.h"

#include "bsp_rf.h"
#include "bsp_BL55072A.h"
#include "mac_receiver.h"
#include "app_key_value.h"
#include "app_hub_api.h"
#include "app_api.h"
#include "app_hub_api_subsidiary.h"
#include "app_broadcast_retry.h"
#include "app_cli_config.h"

#include "util.h"
#include "mac_fhss.h"
#include "mac_timeSync.h"
#include "app_filetransport_api.h"

static bool net_printf_log = false;
static uint8_t packet_tx[DATA_LINK_LENGTH];
static uint8_t callback_type; // 回调类型
// static uint8_t packet_rx[DATA_LINK_LENGTH];
// static uint8_t packet_rx_size;

static uint8_t net_upload_kv_buff[DATA_LINK_LENGTH]; // 上报用结构体
static uint16_t net_upload_kv_size = 0;              // 上报用

static uint8_t broadcast_data[DATA_LINK_LENGTH]; // hub 广播下发用；
static uint8_t broadcast_data_size = 0;

static bool s_updateMeAppEn = false; // 强制保活开启

#ifdef RFM_DEVICE
static bool old_isRSSI = 0; // qrfh1 rssi
#endif

typedef enum
{
    NET_PARAM_TPMODE,
    NET_PARAM_BURSTMODE,
    NET_PARAM_VERSION,
    NET_PARAM_MACADD2,
    NET_PARAM_PANID,
    NET_PARAM_DESTID,
    NET_PARAM_SRCID,
    NET_PARAM_ROUTID,
    NET_PARAM_RSSI,
    NET_PARAM_ECHASEQ,
    NET_PARAM_ISACKBCAST,
    NET_PARAM_ISCONFIGREQ,
    NET_PARAM_ISRXALWAYSON,
    NET_PARAM_ISSPVNEN,
    NET_PARAM_ISACKREQ,
    NET_PARAM_IOEN,
    NET_PARAM_ISAUTOPOWER,
    NET_PARAM_ISRXWAKE,
    NET_PARAM_ISMAXPOWER,
    NET_PARAM_ISRSSI,
    NET_PARAM_ISFM,
    NET_PARAM_ISUM,
    NET_PARAM_BSEQ,
    NET_PARAM_BRETRY,
} NET_PARAM_E;

// net ack控制
typedef struct
{
    uint8_t destID; // 目的地址
    uint8_t cmd;    // 应答的cmd
} net_ack_t;
net_ack_t net_ack;

// net p2p（downlink）
typedef struct
{
    uint8_t destID;                      // 目的地址
    uint8_t key_value[DATA_LINK_LENGTH]; // 物模型
    uint8_t key_value_size;              // 物模型大小
    uint8_t cmd;                         // 应答的cmd

} net_p2p_t;
net_p2p_t net_p2p[DOWNLINK_CONCURRENCY_CAPABILITY]; // 数量为点对点并发数

typedef struct
{
    // frameCtl字段 tpMode burstMode version
    bool tpMode;    // 0 表示星形，1 表示 Mesh；
    bool burstMode; // 置 1 表示当前 HUB 所处系统正在进行大数据传输中，
                    // 报文为数据传输报文，其报文头部可被精简；
    uint8_t version;
    uint16_t macAdd2;
    uint32_t panId;
    uint32_t sysId;
    uint8_t txdestID;
    uint8_t routID; // mesh only
    uint8_t rssi;
#ifdef RFM_DEVICE
    uint8_t rfmid; // 初始化和while通过判断是否注册获取本机地址
#endif

    bool needAutoIsUM;
    uint8_t isUmCount;
    uint8_t isUm_MAXtimes;
    uint8_t aseq[ASEQ_NUM];
    // broadcast
    uint8_t bseq[3]; // 0 SOUNDER  1 KEYPAD  2 SWITCH
    BTYPE_E btype;
    uint8_t bretry; // TODU:bretryCount区别？
    uint8_t ackCtrl;
    uint8_t bretryAckCtrl;
    // broadcast bretry
    char oneway[10];
    int oneway_size;
    char twoway[200]; // 组合广播时数据较多
    int twoway_size;
    char bretryCount;
    char bd_flag; // HUB用于判断广播
    char ota_flag;
} net_t;
static net_t net;

// extern Buffer_t buff_key_value_down; // 下行物模型队列
extern Buffer_t buff_key_value_up; // 上行物模型队列

void net_param_init(void)
{
    uint8_t buff[8];
    // 获取macAdd2
    getThisParam(ENpbyMacID, buff);
    net.macAdd2 = l_get_be64(buff) & 0xffff;
#ifdef CONFIG_LOG_NET_PACKET
    if (net_printf_log)
    {
        APP_PRINTF_HEX("mac:", buff, 8);
        DS_app_log_debug("MacID:0x%04X\r\n", net.macAdd2);
    }
#endif
    // 获取PanId
    net.panId = readThisSystemId(); // 修改为systemID,作废readThisPanId();
    init_aseq();                    // 初始化aseq
    net.needAutoIsUM = false;
    net.isUmCount = 0;
    net.isUm_MAXtimes = 0;

#ifdef RFM_DEVICE
    // bseq rfm 0   HUB由linux控制
    net.bseq[0] = 0;
    net.bseq[1] = 0;
    net.bseq[2] = 0;
#endif
}

static uint8_t pack_frameCtl(bool tpMode, bool burstMode, uint8_t version)
{
    return tpMode << FRAMECTL_TPMODE_POS |
           burstMode << FRAMECTL_BURSTMODE_POS |
           (version & FRAMECTL_VERSION_MASK);
}
static void unpack_frameCtl(uint8_t frameCtl, bool *tpMode, bool *burstMode, uint8_t *version)
{
    *tpMode = frameCtl & FRAMECTL_TPMODE_MASK;
    *burstMode = frameCtl & FRAMECTL_BURSTMODE_MASK;
    *version = frameCtl & FRAMECTL_VERSION_MASK;
}

/***********ISUM***********/
#ifdef RFM_DEVICE
static MultiTimer isUmTimer = {.Handle = 0x1000};
static uint32_t isUmTimer_time = 0; // 保活定时器时间，单位ms

void isUmTimerCallback(MultiTimer *timer, void *userData) // 注意这里是中断
{
    (void)userData;
    (void)timer;

    uint8_t temp_u8 = getThisQrfH2();
    QRFH2_t rfmQrfH2 = U8_TO_QRFH2(temp_u8);
    old_isRSSI = rfmQrfH2.isRSSI; // rssi查询赋值
    net.isUmCount++;
    if (net_printf_log)
        printf("umcnt(%d)%d ", net.isUm_MAXtimes, net.isUmCount);
    if (net.isUmCount > net.isUm_MAXtimes)
    {
        net.isUmCount = 0;
        net.isUm_MAXtimes = 0;
        rfmQrfH2.isUM = QRF_ISUM_NONE;
        temp_u8 = QRF_TO_U8(rfmQrfH2);
        setThisQrfH2(&temp_u8); // 通信异常超时关
        return;
    }

    isUmTimerStart(isUmTimer_time); // 重启定时器

    if (checkMacTransEvent(EN_TRANS_REQ_SPVN) == 0)
    {
        if (net_printf_log)
            printf("ck:SP");
        setMacTransEvent(EN_TRANS_REQ_SPVN, ADDRESS_HUB, ADHOC_RETRY_COUNT_MAX, LBT_REDO_COUNT_MAX);
    }
    if (net_printf_log)
        printf("\r\n");
}

void isUmTimerStart(uint32_t ms) //  1/32768 s
{
    isUmTimer_time = ms;
    softwareMultiTimerStop(EN_LP_HARD_TIMER_EM3_SYS_RTC_1, &isUmTimer, 0);
    softwareMultiTimerStart(EN_LP_HARD_TIMER_EM3_SYS_RTC_1, &isUmTimer, ms * 32768 / 1000, isUmTimerCallback, NULL, 1);
    if (net_printf_log)
        printf("isTS:%ld\r\n", ms);
}

#endif
// 修改用于循环解接收物模型
//*pkv 物模型数组
// len  物模型数组大小
void net_unpack_kv(uint8_t destID, uint8_t *pkv, uint8_t len) //Info0430 此处仅为判断自动保活，应在取物模型处，进行判断和赋值 自动保活标志
{
    (void)destID;
    net.needAutoIsUM = false; // 自动保活标志
    //for (uint8_t pos = 0; pos < len; )
    for (uint8_t pos = 0; pos < len; pos++)
    {
        uint8_t key_id = pkv[pos++];
        // 物模型长度
        uint8_t value_size = get_key_value_size(key_id); // value_size 除key-id以外的长度
        if (APP_KEY_VALUE_SIZE_IS_AVR == value_size)
        {
            value_size = pkv[pos++] + 1; // 可变长度
            if (value_size == 1) // 可变长度字段为0时认为数据错误，丢弃本次物模型
             break;
        }
        // 需要保活的物模型 后续可扩充
        if (key_id == APP_KEY_VALUE_ID_KEY_PRESS ||
            key_id == APP_KEY_VALUE_ID_KEY_MULTI_PRESS)
        {
#ifdef RFM_DEVICE
            net.needAutoIsUM = true; // 自动保活
#endif
        }
//        else if (APP_KEY_VALUE_ID_OPTION == key_id) // 0x50 hub保存物模型，已移到HUB APP层解析处
//        {
//
//        }
        pos += value_size;
    }
}

void isUMPorcess() // 子设备每次收到报文都会进来处理，TODO:考虑不在收到报文开始重新计时
{
#if defined(RFM_DEVICE)
    uint8_t temp_u8 = getThisQrfH2();
    QRFH2_t rfmQrfH2 = U8_TO_QRFH2(temp_u8);
    if (net_printf_log)
        printf("UM:%d ", rfmQrfH2.isUM);

    if (s_updateMeAppEn == true) // APP强制保活开启，开启2s
    {
        if (rfmQrfH2.isUM == QRF_ISUM_NONE) // 当HUB远程设置QRF isUM开启时，优先使用该值，否则使用本地APP控制字段
        {
            rfmQrfH2.isUM = QRF_ISUM_2S;
            temp_u8 = QRF_TO_U8(rfmQrfH2);
            setThisQrfH2(&temp_u8); // 保活未开启，收到app强制保活开启，开启默认2s
        }
    }

    if (net.needAutoIsUM == true) // 自动保活提前处理
    {
        net.isUm_MAXtimes = 1;
        net.isUmCount = 0;
        isUmTimerStart(1000); // 自动保活一次
    }
    else
    {
        switch (rfmQrfH2.isUM) // 重传(保活)20次失败，自动退出，置0
        {
        case QRF_ISUM_NONE: // 不保活
            break;
        case QRF_ISUM_2S: // 间隔2s 上报
            net.isUmCount = 0;
            net.isUm_MAXtimes = 5; // 最大10s保活
            isUmTimerStart(2000);
            break;
        case QRF_ISUM_1S: // 间隔1s 上报
            net.isUmCount = 0;
            net.isUm_MAXtimes = 10; // 最大10s保活
            isUmTimerStart(1000);
            break;
        case QRF_ISUM_0_5S: // 间隔0.5s 上报
            net.isUmCount = 0;
            net.isUm_MAXtimes = 20; // 最大10s保活
            isUmTimerStart(500);
            break;
        default:
            break;
        }
    }
    if (rfmQrfH2.isUM == QRF_ISUM_NONE && (net.needAutoIsUM == false))
    {
        if (rfmQrfH2.isRSSI) // 3min / 6s
        {
            net.isUmCount = 0;
            net.isUm_MAXtimes = 30;
            if (rfmQrfH2.isRSSI == old_isRSSI) // TODO:RSSI == old 不开启start是否可行？
                isUmTimerStart(6000);
            else
                isUmTimerStart(2000);
            isUmTimer_time = 6000; // 定时器中重新使用6s
        }
        else if (rfmQrfH2.isFM) // 3min / 18S
        {
            net.isUmCount = 0;
            net.isUm_MAXtimes = 10;
            isUmTimerStart(18000);
        }
        else
        {
            net.isUmCount = net.isUm_MAXtimes;
        }
    }
    net.needAutoIsUM = false;
#endif
}

/***********BROADCAST***********/
void unpackBretryAckCtrl(uint8_t bretryAckCtrl)
{
    net.bretry = GET_BRETRY(bretryAckCtrl);
    net.ackCtrl = GET_ACKCTRL(bretryAckCtrl);
}

/***********OPTION***********/
// hub 下行操作 如有新操作物模型需在此添加
/*
ack_kv_buff 应答物模型
ack_kv_size 应答物模型长度
*/
void net_hub_down_option(uint8_t device_id, uint8_t *ack_kv_buff, uint16_t *ack_kv_size)
{
    // 下行物模型
    memset(ack_kv_buff, 0, DATA_LINK_LENGTH); // HUB应答用
    uint8_t led_ctrl_flag = 0;
    uint8_t operate_ctrl_flag = 0;
    uint8_t keyvalue_get_flag = 0;
    uint8_t OtaConSult_Flag = 0;
    getDeviceParam(device_id, ENbyLedCtrlFlag, &led_ctrl_flag);
    getDeviceParam(device_id, ENbyOperateCtrlFlag, &operate_ctrl_flag);
    getDeviceParam(device_id, ENbyKeyValueGetFlag, &keyvalue_get_flag);
    getDeviceParam(device_id, ENbyOtaConSultFlag, &OtaConSult_Flag);

#ifdef CONFIG_LOG_NET_PACKET
    if (net_printf_log)
        DS_app_log_debug("led_ctrl_flag:%d\r\n", led_ctrl_flag);
#endif
    // 收到0XFF后的网关应答0xfe物模型
    if (OtaConSult_Flag)
    {
        // 直接清flag
        OtaConSult_Flag = 0;
        setDeviceParam(device_id, ENbyOtaConSultFlag, &OtaConSult_Flag);
        //  物模型
        getThisParam(ENbyOtaConSultKeyValue, ack_kv_buff + ack_kv_size[0]); // 含key id
        if (net_printf_log)
            APP_PRINTF_HEX("OCS:", ack_kv_buff + ack_kv_size[0], OTA_CONSULT_KEYVALUE_LENGTH);
        ack_kv_size[0] += OTA_CONSULT_KEYVALUE_LENGTH;
    }
    // 仅有操作输出物模型需要更新aseq
    if (led_ctrl_flag)
    {
        // 物模型
        ack_kv_buff[ack_kv_size[0]++] = APP_KEY_VALUE_ID_COMLED_CTRL;
        getDeviceParam(device_id, ENbyLedCtrl, ack_kv_buff + ack_kv_size[0]);
        ack_kv_buff[ack_kv_size[0]] = get_node_aseq(ASEQ_LED, device_id); // 协议栈使用
        if (net_printf_log)
            APP_PRINTF_HEX("lc:", ack_kv_buff + ack_kv_size[0] - 1, LEDCTRL_LENGTH + RBF_MAC_PACKET_LEN_SIZE);
        ack_kv_size[0] += LEDCTRL_LENGTH;
        // 初始子设备 直接清flag 确保下次注册该地址重复初始化
        if (0x00 == ack_kv_buff[ack_kv_size[0] - 1] &&
            0x00 == ack_kv_buff[ack_kv_size[0] - 2] &&
            TEST_RFM_CMD_STOP > ack_kv_buff[ack_kv_size[0] - 3] &&
            0xCA == ack_kv_buff[ack_kv_size[0] - 4] &&
            0xDE == ack_kv_buff[ack_kv_size[0] - 5])
        {
#if 0 // 不需要清flag 测试删除时会清
            led_ctrl_flag = 0;
            uint8_t led_ctr[LEDCTRL_LENGTH] = {0};
            setDeviceParam(device_id, ENbyLedCtrlFlag, &led_ctrl_flag); // 清flag
            setDeviceParam(device_id, ENbyLedCtrlFlag, &led_ctr);       // 清物模型
#endif
#if 0 // 删除子设备cli指令
            if (device_id != ADDRESS_HUB &&
                device_id != ADDRESS_BROADCAST)
            { // 恢复子设备出厂设置，HUB删除子设备注册信息
                uint8_t cliBuff[20] = {0};
                sprintf(cliBuff, "DeleteRfm,%d\r", device_id); // cli指令
                for (uint8_t i = 0; i < strlen(cliBuff); i++)
                {
                    bufferAdd(&debug_RXBuff, cliBuff[i]);
                }
            }
#endif
        }
    }
    if (operate_ctrl_flag)
    {
        // 物模型
        ack_kv_buff[ack_kv_size[0]++] = APP_KEY_VALUE_ID_OPERATE_CTRL;
        getDeviceParam(device_id, ENbyOperateCtrl, ack_kv_buff + ack_kv_size[0]);
        ack_kv_buff[ack_kv_size[0]] = get_node_aseq(ASEQ_OPERATE, device_id);
        if (net_printf_log)
            APP_PRINTF_HEX("oc:", ack_kv_buff + ack_kv_size[0] - 1, OPERATECTRL_LENGTH + RBF_MAC_PACKET_LEN_SIZE);
        ack_kv_size[0] += OPERATECTRL_LENGTH;
    }

#if 0 // TODO
#ifdef CONFIG_LOG_NET_PACKET
    DS_app_log_debug("keyvalue_get_flag:%d\r\n", keyvalue_get_flag);
#endif
    if (keyvalue_get_flag)
    {
        ack_kv_buff[ack_kv_size[0]] = APP_KEY_VALUE_ID_KEY_VALUE_GET;
        ack_kv_size[0]++;
        getDeviceParam(device_id, ENbyKeyValueGet, ack_kv_buff + ack_kv_size[0]);
#ifdef CONFIG_LOG_NET_PACKET
    if (net_printf_log)
        APP_PRINTF_HEX("keyvalue_get:", ack_kv_buff + ack_kv_size[0], GETKEYVALUE_LENGTH + RBF_MAC_PACKET_LEN_SIZE);
#endif
        ack_kv_size[0] += OPERATECTRL_LENGTH;
    }
#endif
    ack_kv_buff[ack_kv_size[0]++] = APP_KEY_VALUE_ID_OPTION;

    if (getDeviceParam(device_id, ENpbyNodeOptionFirst, ack_kv_buff + ack_kv_size[0]))
    { // option读不出来默认0
        uint8_t buff[3] = {0};
        setDeviceParam(device_id, ENpbyNodeOptionFirst, buff);
        memcpy(ack_kv_buff + ack_kv_size[0], buff, OPTION_LENGTH);
#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
            DS_app_log_debug("No Node(0x%02X) Option \r\n", device_id);
#endif
    }
    ack_kv_size[0] += OPTION_LENGTH;
}

void net_hub_clean_option(uint8_t device_id)
{
    uint8_t data = 0;

    if (check_aseq(ASEQ_LED, device_id, net.aseq[ASEQ_LED]))
    {
        setDeviceParam(device_id, ENbyLedCtrlFlag, &data);
    }
    if (check_aseq(ASEQ_OPERATE, device_id, net.aseq[ASEQ_OPERATE]))
    {
        setDeviceParam(device_id, ENbyOperateCtrlFlag, &data);
    }
}

// mac打印
void Log_RF(void)
{
    if (net_printf_log)
    {
        RF_PACKET_ST *pPacket = getLastRecvPacketPoint();
        if (pPacket == NULL)
            printf("*pPacket=NULL\r\n");
        printf("RCh%d-%d,R:%d,Ant%d,AFC:%dHz\r\n",
               pPacket->details.channelHoppingChannelIndex, pPacket->details.channel, pPacket->details.rssi, pPacket->details.antennaId, pPacket->AfcError);
    }
}
// 报头打印
void Log_hdr(RBFMacHeader_t hdr)
{
    if (net_printf_log)
        DS_app_log_error("ID:%02X dID:%02X PID:%06X RC:%08X CD:%02X ",
                         hdr.srcId, hdr.destID, hdr.panId, (unsigned int)hdr.rollungCode, hdr.cmd);
}
// 指令msg打印
void Log_msg(RBF_CMD_TYPE cmd, void *pmsg)
{
    if (net_printf_log)
    {
        if (pmsg == NULL)
        {
            printf("msg=NULL\r\n");
            return;
        }
        switch (cmd)
        {
        case RBF_CMD_NODE_UPLOAD_EVENT: // 节点实时事件上报
        {
            RBFMacMessageNodeUploadEvent_t *msg = (RBFMacMessageNodeUploadEvent_t *)pmsg;
            printf("MC:%04X SQ:%02X RT:%02X BT:%02X RD:%02X TP:%02X R1:%02X R2:%02X ",
                   msg->macAdd, msg->msgSeq, msg->msgRetry, msg->battV, msg->rssi, msg->temp, msg->qrfR1, msg->qrfR2);
            APP_PRINTF_HEX("kv:", msg->keyValue, msg->keyValueSize);
        }
        break;
        case RBF_CMD_NODE_UPLOAD_HEARTBEAT: // 节点心跳上报
        {
            RBFMacMessageNodeUploadHeartbeat_t *msg = (RBFMacMessageNodeUploadHeartbeat_t *)pmsg;
            printf("MC:%04X SQ:%02X RT:%02X BT:%02X RD:%02X TP:%02X R1:%02X R2:%02X ",
                   msg->macAdd, msg->msgSeq, msg->msgRetry, msg->battV, msg->rssi, msg->temp, msg->qrfR1, msg->qrfR2);
            APP_PRINTF_HEX("kv:", msg->keyValue, msg->keyValueSize);
        }
        break;
        case RBF_CMD_GATEWAY_ACK_EVENT: // 网关应答上报
        {
            RBFMacMessageGWAckEvent_t *msg = (RBFMacMessageGWAckEvent_t *)pmsg;
            printf("RD:%02X H1:%02X H2:%02X ", msg->rssi, msg->qrfH1, msg->qrfH2);
            APP_PRINTF_HEX("kv:", msg->keyValue, msg->keyValueSize);
        }
        break;
        case RBF_CMD_GATEWAY_ACK_HEARTBEAT: // 网关心跳上报
        {
            RBFMacMessageGWAckHeartbeat_t *msg = (RBFMacMessageGWAckHeartbeat_t *)pmsg;
            printf("RD:%02X H1:%02X H2:%02X ", msg->rssi, msg->qrfH1, msg->qrfH2);
            APP_PRINTF_HEX("kv:", msg->keyValue, msg->keyValueSize);
        }
        break;
        case RBF_CMD_GATEWAY_DOWNLOAD: // 网关主动下发
        {
            RBFMacMessageGWDownload_t *msg = (RBFMacMessageGWDownload_t *)pmsg;
            printf("MC:%04X SQ:%02X RT:%02X RD:%02X H1:%02X H2:%02X ", msg->macAdd, msg->msgSeq, msg->msgRetry, msg->rssi, msg->qrfH1, msg->qrfH2);
            APP_PRINTF_HEX("kv:", msg->keyValue, msg->keyValueSize);
        }
        break;
        case RBF_CMD_NODE_ACK: // 节点应答
        {
            RBFMacMessageNodeAck_t *msg = (RBFMacMessageNodeAck_t *)pmsg;
            printf("BT:%02X RD:%02X TP:%02X R1:%02X R2:%02X ", msg->battV, msg->rssi, msg->temp, msg->qrfR1, msg->qrfR2);
            APP_PRINTF_HEX("kv:", msg->keyValue, msg->keyValueSize);
        }
        break;
        case RBF_CMD_GATEWAY_SYNC_BROADCAST: // 网关同步广播
        {
            RBFMacMessageGWBoardcast_t *msg = (RBFMacMessageGWBoardcast_t *)pmsg;
            printf("BA:%02X BT:%02X ", msg->bretryAckCtrl, msg->bTypeData[0]);
            APP_PRINTF_HEX("bd:", msg->bTypeData, msg->bTypeDataSize);
        }
        break;
        case RBF_CMD_GATEWAY_NOMAL_BROADCAST: // 网关普通广播
        {
            RBFMacMessageGWBoardcast_t *msg = (RBFMacMessageGWBoardcast_t *)pmsg;
            printf("BA:%02X BT:%02X ", msg->bretryAckCtrl, msg->bTypeData[0]);
            APP_PRINTF_HEX("bd:", msg->bTypeData, msg->bTypeDataSize);
        }
        break;
        default:
            break;
        }
    }
}

// 接收打印
void Log_rx(RBFMacHeader_t hdr, void *pmsg)
{
    Log_RF(); // 射频打印
    if (net_printf_log)
        printf("R");
    Log_hdr(hdr);
    Log_msg(hdr.cmd, pmsg);
}
// 发送打印
void Log_tx(RBFMacHeader_t hdr, void *pmsg)
{
    if (net_printf_log)
        printf("T");
    Log_hdr(hdr);
    Log_msg(hdr.cmd, pmsg);
}

// 打包
void net_pack(uint8_t destID, uint8_t *packet, uint8_t cmd, void *pdata)
{
    uint8_t ret;
    RBFMacHeader_t hdr;
    // uint8_t _key[RBF_KEY_LENGTH_MAX] = {0};
    // uint8_t buff[8];

#ifdef RFM_DEVICE
    net.panId = readThisSystemId(); // 修改systemID,作废readThisPanId();
#endif
    memset(packet, 0, DATA_LINK_LENGTH);
    // heander
    hdr.rollungCode = get_device_itself_rolling_code();
    net.version = RBF_VERSION;
    hdr.frameCtl = pack_frameCtl(net.tpMode, net.burstMode, net.version);
    hdr.panId = net.panId;
#ifdef RFM_DEVICE
    hdr.srcId = net.rfmid;
#else
    hdr.srcId = ADDRESS_HUB;
#endif
    hdr.destID = destID; // 目的地址
    hdr.cmd = cmd;
    RBF_packet_build_header(hdr, packet);

    // payload
    switch (hdr.cmd) //
    {
#ifdef RFM_DEVICE
    case RBF_CMD_NODE_UPLOAD_EVENT:
    {
        net_pack_t *net_pack_pdata = (net_pack_t *)pdata;
        RBFMacMessageNodeUploadEvent_t msg = {
            // 测试msg
            .macAdd = net.macAdd2,
            .msgSeq = get_msgSeq(),
            .msgRetry = net_pack_pdata->retry,
            .battV = SM_battery_get(), // 获取电池电压
            .rssi = net.rssi,          // 获取RSSI值
            .temp = SM_tempDrv_get(),  // 获取核心温度
            .qrfR1 = getThisQrfR1(),
            .qrfR2 = getThisQrfR2(),
            .echASeq = 0,
            .keyValueSize = net_upload_kv_size,
            .keyValue = net_upload_kv_buff,
        };
        net_unpack_kv(hdr.destID, net_upload_kv_buff, net_upload_kv_size); // 这里解析有键盘或遥控器物模型需要自动保活
        RBF_node_upload_event_payload_msgToPacket(msg, packet);
        Log_tx(hdr, &msg);
    }
    break;
    case RBF_CMD_NODE_UPLOAD_HEARTBEAT:
    {
        net_pack_t *net_pack_pdata = (net_pack_t *)pdata;
        uint8_t net_heartbeat_kv_buff[DATA_LINK_LENGTH]; // 心跳用结构体
        uint8_t net_heartbeat_kv_size = 0;               // 心跳用结构体
        net_heartbeat_kv_buff[net_heartbeat_kv_size++] = APP_KEY_VALUE_ID_ACKCTRLRECVD;
        net_heartbeat_kv_buff[net_heartbeat_kv_size++] = APP_KEY_VALUE_ID_COMLED_CTRL;
        net_heartbeat_kv_buff[net_heartbeat_kv_size++] = get_aseq(ASEQ_LED);
        net_heartbeat_kv_buff[net_heartbeat_kv_size++] = APP_KEY_VALUE_ID_OPERATE_CTRL;
        net_heartbeat_kv_buff[net_heartbeat_kv_size++] = get_aseq(ASEQ_OPERATE);

        net_heartbeat_kv_size += get_device_state(net_heartbeat_kv_buff + net_heartbeat_kv_size);
        RBFMacMessageNodeUploadHeartbeat_t msg = {
            // 测试msg
            .macAdd = net.macAdd2,
            .msgSeq = get_msgSeq(),
            .msgRetry = net_pack_pdata->retry,
            .battV = SM_battery_get(), // 获取电池电压
            .rssi = net.rssi,          // 获取RSSI值
            .temp = SM_tempDrv_get(),  // 获取核心温度
            .qrfR1 = getThisQrfR1(),
            .qrfR2 = getThisQrfR2(),
            .echASeq = 0,
            .keyValueSize = net_heartbeat_kv_size,
            .keyValue = net_heartbeat_kv_buff,
        };
        RBF_node_upload_heart_payload_msgToPacket(msg, packet);
        Log_tx(hdr, &msg);
    }
    break;
#else
    case RBF_CMD_GATEWAY_ACK_EVENT:
    {
        // 获取物模型
        uint8_t ack_kv_buff[DATA_LINK_LENGTH]; // 应答用结构体局部变量
        uint16_t ack_kv_size = 0;              // 应答用结构体

        net_hub_down_option(hdr.destID, ack_kv_buff, &ack_kv_size); // 下行操作
        RBFMacMessageGWAckEvent_t msg = {
            .rssi = net.rssi,
            .aseq = 0,
            .qrfH1 = getDevicQrfH1(hdr.destID),
            .qrfH2 = getDevicQrfH2(hdr.destID),
            .keyValueSize = ack_kv_size,
            .keyValue = ack_kv_buff,
        };
        RBF_gw_ack_event_payload_msgToPacket(msg, packet);
        Log_tx(hdr, &msg);
    }
    break;
    case RBF_CMD_GATEWAY_ACK_HEARTBEAT:
    {
        // 获取物模型
        uint8_t ack_kv_buff[DATA_LINK_LENGTH]; // 应答用结构体局部变量
        uint16_t ack_kv_size = 0;              // 应答用结构体

        net_hub_down_option(hdr.destID, ack_kv_buff, &ack_kv_size); // 下行操作
        RBFMacMessageGWAckHeartbeat_t msg = {
            .rssi = net.rssi,
            .qrfH1 = getDevicQrfH1(hdr.destID),
            .qrfH2 = getDevicQrfH2(hdr.destID),
            .aseq = 0,
            .keyValueSize = ack_kv_size,
            .keyValue = ack_kv_buff,
        };
        RBF_gw_ack_heart_payload_msgToPacket(msg, packet);
        Log_tx(hdr, &msg);
    }
    break;
    case RBF_CMD_GATEWAY_DOWNLOAD:
    {
        net_pack_t *net_pack_pdata = (net_pack_t *)pdata;
        uint8_t mac[MAC_ADDRESS_LENGTH] = {0};
        getNodeJoinMac(mac, hdr.destID);
        uint16_t devMacAdd2 = l_get_be64(mac) & 0xffff;
        RBFMacMessageGWDownload_t msg = {
            .macAdd = devMacAdd2,
            .msgSeq = get_msgSeq(),
            .msgRetry = net_pack_pdata->retry,
            .qrfH1 = getDevicQrfH1(hdr.destID),
            .qrfH2 = getDevicQrfH2(hdr.destID),
            .rssi = net.rssi,
            .keyValueSize = net_p2p[net_pack_pdata->p2p_ch].key_value_size,
            .keyValue = net_p2p[net_pack_pdata->p2p_ch].key_value,
        };
        RBF_gw_download_payload_msgToPacket(msg, packet);
        Log_tx(hdr, &msg);
    }
    break;
#endif
#ifdef RFM_DEVICE
    case RBF_CMD_NODE_ACK:
    {
        uint8_t ack_key_valu_buff[DATA_LINK_LENGTH] = {0};
        uint8_t ack_key_valu_size = 0;
        ack_key_valu_size = get_device_state(ack_key_valu_buff); // 上报设备状态
        RBFMacMessageNodeAck_t msg = {
            .battV = SM_battery_get(),
            .rssi = net.rssi,
            .temp = SM_tempDrv_get(),
            .qrfR1 = getThisQrfR1(),
            .qrfR2 = getThisQrfR2(),
            .keyValueSize = ack_key_valu_size,
            .keyValue = ack_key_valu_buff,
        };
        RBF_node_ack_payload_msgToPacket(msg, packet);
        Log_tx(hdr, &msg);
    }
    break;
#else
    case RBF_CMD_GATEWAY_SYNC_BROADCAST:
    {
        uint8_t buf[3];
        getThisParam(ENpbySystemID, buf);
        net.sysId = l_get_be24(buf);
        RBFMacMessageGWBoardcast_t msg = {
            .systemId = net.sysId,
            .bretryAckCtrl = net.bretryAckCtrl,
            .bTypeDataSize = broadcast_data_size,
            .bTypeData = broadcast_data,
        };
        RBF_gw_broadcast_payload_msgToPacket(msg, packet);
        Log_tx(hdr, &msg);
    }
    break;
    case RBF_CMD_GATEWAY_NOMAL_BROADCAST:
    {
        uint8_t buf[3];
        getThisParam(ENpbySystemID, buf);
        net.sysId = l_get_be24(buf);
        RBFMacMessageGWBoardcast_t msg = {
            .systemId = net.sysId,
            .bretryAckCtrl = net.bretryAckCtrl,
            .bTypeDataSize = broadcast_data_size,
            .bTypeData = broadcast_data,
        };
        RBF_gw_broadcast_payload_msgToPacket(msg, packet);
        Log_tx(hdr, &msg);
    }
    break;
#endif
    // case RBF_CMD_NODE_ROAMING:
    // {
    // }
    // break;
    default:
        if (net_printf_log)
            DS_app_log_error("cmd (0x%02X) not support!\r\n", hdr.cmd);
        return;
        break;
    }
    // 加密
    ret = mac_payload_crypto(packet);
    if (SECURE_ELEMENT_SUCCESS != ret)
    {
        if (net_printf_log)
            DS_app_log_error("crypto ret=%d\r\n", ret);
    }
}

/*
 *心跳或事件上报处理
 *输入：packet   数据报文
 *       hdr      报头解析数据结果
 */
void net_upload_event_process(uint8_t *packet, RBFMacHeader_t hdr)
{
#ifdef HUB_DEVICE
    RBFMacMessageNodeUploadEvent_t msg;
    RBF_node_upload_event_payload_packetToMsg(packet, &msg);

    // 网络层物模型（hub 解物模型）
    if (msg.keyValue[0] == APP_KEY_VALUE_ID_BCASTRECVD)
    {
        uint8_t kv_size = msg.keyValue[1] + 1; // Len+(Btype+Bseq)[N]
        maybe_receve_rfm_broadcast_respons(hdr.srcId, msg.keyValue + 1, kv_size);

        // 接收删除0x2f物模型（未验证）
        // kv_size++; // 加上key-id
        // memmove(msg.keyValue, msg.keyValue + kv_size, msg.keyValueSize - kv_size);
    }
    else if (msg.keyValue[0] == APP_KEY_VALUE_ID_ACKCTRLRECVD)
    {
        uint8_t pos = 1;
        uint8_t len = APP_KEY_VALUE_ACKCTRLRECVD_SIZE;
        for (int N = 0; N < len / 2; N++)
        {
            uint8_t ctrlKey = msg.keyValue[pos++];
            if (ctrlKey == APP_KEY_VALUE_ID_COMLED_CTRL)
                net.aseq[ASEQ_LED] = msg.keyValue[pos++];
            else if (ctrlKey == APP_KEY_VALUE_ID_OPERATE_CTRL)
                net.aseq[ASEQ_OPERATE] = msg.keyValue[pos++];
        }
        net_hub_clean_option(hdr.srcId);
    }

    setDevicQrfR1(hdr.srcId, &msg.qrfR1); // R1
    setDevicQrfR2(hdr.srcId, &msg.qrfR2); // R2

    app_key_value_unpack(msg.keyValue, msg.keyValueSize);           // 生产物模型队列 TODO：考虑删除不执行是否有影响
    set_cmd_ack(1);                                                 // 需要应答ACK
    net_ack.destID = hdr.srcId;                                     // 上报(心跳/事件)应答
    setMacTransEvent(EN_TRANS_REQ_ADHOC_SPVN_ACK, hdr.srcId, 0, 0); // 应答之
    Log_rx(hdr, &msg);
#else
    (void)packet;
    (void)hdr;
#endif
}

/*
 *应答心跳或事件上报处理
 *输入：packet   数据报文
 *       hdr      报头解析数据结果
 */
void net_ack_upload_process(uint8_t *packet, RBFMacHeader_t hdr)
{
#ifdef RFM_DEVICE
    RBFMacMessageGWAckEvent_t msg;
    RBF_gw_ack_event_payload_packetToMsg(packet, &msg);

    setThisQrfH1(&msg.qrfH1); // RFM收到QRFH1,set
    QRFH1_t rfmQrfH1 = U8_TO_QRFH1(msg.qrfH1);
    setThisQrfH2(&msg.qrfH2); // RFM收到QRFH2,set
    QRFH2_t rfmQrfH2 = U8_TO_QRFH2(msg.qrfH2);

    SM_device_QRF_state_Handle(rfmQrfH1, rfmQrfH2);

    // 解析找出物模型 0xFE
    keyValue_t keyValue;
    for (uint8_t pos = 0; pos < msg.keyValueSize;)
    {
        keyValue.id = msg.keyValue[pos++];
        keyValue.valueSize = get_key_value_size(keyValue.id);
        if (APP_KEY_VALUE_SIZE_IS_AVR == keyValue.valueSize)
        {
            if (msg.keyValue[pos] == 0) // 可变长度字段为0时认为数据错误，丢弃本次物模型
                break;
            keyValue.valueSize = msg.keyValue[pos] + 1;
        }
        switch (keyValue.id)
        {
        case APP_KEY_VALUE_ID_COMLED_CTRL: // 灯控物模型 kId + seq + RGB + TIME + CYCLE 7字节
            // msg.keyValue[pos+0]是SEQ
            if (0x00 == msg.keyValue[pos + 4] && 0x00 == msg.keyValue[pos + 5]) // Time、Cycle均为0时
            {
                if (0xDE == msg.keyValue[pos + 1] &&
                    0xCA == msg.keyValue[pos + 2])
                {                                  // RGB：0xDE CA 01时表示格式化
                    switch (msg.keyValue[pos + 3]) // TEST CMD  产测指令
                    {
                    case TEST_RFM_CMD_FACTORY: // 子设备恢复初始化
                        rfm_formatting();
                        break;
                    case TEST_RFM_CMD_TH_DISPLAY_ALL_ON: // 温湿度计全屏显示
#ifdef SM_TEMPHUMI
                        LCD_DIS_all(1);
#endif
                        break;
                    case TEST_RFM_CMD_TH_DISPLAY_ALL_OFF: // 温湿度计全屏熄灭
#ifdef SM_TEMPHUMI
                        LCD_DIS_all(2);
#endif
                        break;
                    case TEST_RFM_CMD_TH_DISPLAY_ALL_EXIT:
#ifdef SM_TEMPHUMI
                        LCD_DIS_all(0);
#endif
                        break;
                    case TEST_RFM_CMD_PL_RESET_CAL: // 清除强电设备校校准参数
#ifdef SM_SMART_PLUG
                        erase_device_data();
#endif
                        break;
                    case TEST_RFM_CMD_CFG_868M:
                        setDeviceRfFreq(RF_FREQ_868MHZ);
                        rfm_formatting();
                        break;
                    case TEST_RFM_CMD_CFG_915M:
                        setDeviceRfFreq(RF_FREQ_915MHZ);
                        rfm_formatting();
                        break;
                    case TEST_RFM_CMD_CFG_433M:
                        setDeviceRfFreq(RF_FREQ_433MHZ);
                        rfm_formatting();
                        break;
                    case TEST_RFM_CMD_CFG_915M_RCM:
                        setDeviceRfFreq(RF_FREQ_915MHZ_RCM);
                        rfm_formatting();
                        break;
                    case TEST_RFM_CMD_CFG_868M_WPC:
                        setDeviceRfFreq(RF_FREQ_868MHZ_WPC);
                        rfm_formatting();
                        break;
                    default:
                        break;
                    }
                }
            }

            break;
        case APP_KEY_VALUE_ID_FILE_TRANS_ACCEPT: // 物模型0xFE
            consumption_deal_consult_keyvalue(msg.keyValue + pos, keyValue.valueSize);
            break;
        default:
            break;
        }
        pos += keyValue.valueSize;
    }
    app_key_value_unpack(msg.keyValue, msg.keyValueSize);         // 压入消费队列
    setMacTxStateEvent(EN_MAC_TX_EVENT_TYPE_WAIT_ACK_DONE, true); // 完成应答

    // RBFMacMessageGWAckEvent_t msg;
    //     Log_RF(); // RF信息打印
    //     DS_app_log_error("RID:%02X dID:%02X PID:%06X RC:%08X CD:%02X H1:%02X H2:%02X ",
    //                      hdr.srcId, hdr.destID, hdr.panId, hdr.rollungCode, hdr.cmd, msg.qrfH1, msg.qrfH2);
    //     APP_PRINTF_HEX("kv:", msg.keyValue, msg.keyValueSize);
    Log_rx(hdr, &msg);
    if (net_printf_log)
    {
        uint8_t temp_u8 = getThisQrfH2();
        QRFH2_t QrfH2 = U8_TO_QRFH2(temp_u8);
        if (QrfH2.isRSSI)
            printf("enRS:%d ", (int)net.rssi);
    }
#else
    (void)packet;
    (void)hdr;
#endif
}

/************************广播物模型***********************************/

// 从ioen广播物模型数据中获取指定ioen
bool get_ioen_from_bd(uint8_t no, uint8_t *data)
{
    uint8_t byte_pos = no / 8;
    uint8_t bit_pos = no % 8;
    return (bool)(data[byte_pos] >> bit_pos & 0x01);
}

// 保存广播物模型ioen
void save_ioen_from_bd(uint8_t *data)
{
    uint8_t no = 0;

#ifdef HUB_DEVICE
    uint8_t rfmid = 0;
    for (no = 0; no < 128; no++)
    {
        rfmid = no + 1;
        uint8_t temp_u8 = getDevicQrfH1(rfmid);
        QRFH1_t hubQrfH1 = U8_TO_QRFH1(temp_u8);
        hubQrfH1.IOen = get_ioen_from_bd(no, data);
        if (hubQrfH1.IOen && net_printf_log)
            printf("id[%d] IOen:%02d\r\n", rfmid, hubQrfH1.IOen);
        temp_u8 = QRF_TO_U8(hubQrfH1);
        setDevicQrfH1(rfmid, &temp_u8);
    }
#else
    uint8_t temp_u8 = getThisQrfH1();
    uint8_t cat = get_cat_from_rfmid(net.rfmid);
    no = get_no_from_cat_rfmid(cat, net.rfmid);
    QRFH1_t rfmQrfH1 = U8_TO_QRFH1(temp_u8);
    rfmQrfH1.IOen = get_ioen_from_bd(no, data);
    temp_u8 = QRF_TO_U8(rfmQrfH1);
    setThisQrfH1(&temp_u8);

    temp_u8 = getThisQrfH2();
    QRFH2_t rfmQrfH2 = U8_TO_QRFH2(temp_u8);
    SM_device_QRF_state_Handle(rfmQrfH1, rfmQrfH2);
    if (net_printf_log)
        printf("[%02x]H1:%02X ", net.rfmid, temp_u8);
#endif
}
bool findIDExitMe(uint8_t *data, uint8_t len, uint8_t rfmid)
{
    if (getThisParam(ENpbyRfmId, &rfmid) != 0) // 无地址
        return false;
    for (uint8_t pos = 0; pos < len; pos++)
    {
        if (rfmid == data[pos])
            return true;
    }
    return false;
}
// UPDATEME 物模型处理  TODO
void BTypeUpdatemeProcess(uint8_t *data)
{
    uint8_t temp_u8;
    uint8_t pos = 0;
    int len = data[pos++];
    uint8_t Ctrl = data[pos++];

    if (net_printf_log)
        printf("LE:%02X CT:%02X ", len, Ctrl);
#ifdef RFM_DEVICE
    if (findIDExitMe(data + pos, len - 1, net.rfmid) == false)
    {
        if (net_printf_log)
            printf("NO FIND ME!\r\n");
        return;
    }
#else
    uint8_t rfmid = 0;
#endif
    switch (Ctrl)
    {
    case 0x00: // 上报心跳并通过应答取数据；
        // need_ack = false;
        // setMacTransEvent(EN_TRANS_REQ_SPVN, ADDRESS_HUB, ADHOC_RETRY_COUNT_MAX, LBT_REDO_COUNT_MAX);
        break;
    case 0x01: // 表示进入Findme，见QRF,
    {
#ifdef HUB_DEVICE
        for (uint8_t no = 0; no < len - 1; no++)
        {
            rfmid = data[pos + no];
            temp_u8 = getDevicQrfH2(rfmid);
            QRFH2_t hubQrfH2 = U8_TO_QRFH2(temp_u8);
            hubQrfH2.isFM = 1;
            temp_u8 = QRF_TO_U8(hubQrfH2);
            setDevicQrfH2(rfmid, &temp_u8);
        }
#else
        temp_u8 = getThisQrfH1();
        QRFH1_t rfmQrfH1 = U8_TO_QRFH1(temp_u8);
        temp_u8 = getThisQrfH2();
        QRFH2_t rfmQrfH2 = U8_TO_QRFH2(temp_u8);
        rfmQrfH2.isFM = 1; // Updateme广播 isFM 查询子设备开启
        temp_u8 = QRF_TO_U8(rfmQrfH2);
        setThisQrfH2(&temp_u8); // Updateme广播 isFM 查询子设备开启
        SM_device_QRF_state_Handle(rfmQrfH1, rfmQrfH2);
        isUMPorcess();
        if (net_printf_log)
            printf("H2:%02X ", temp_u8);
#endif
    }
    break;
    case 0x02: // 表示退出Findme，见QRF
    {
#ifdef HUB_DEVICE
        for (uint8_t no = 0; no < len - 1; no++)
        {
            rfmid = data[pos + no];
            temp_u8 = getDevicQrfH2(rfmid);
            QRFH2_t hubQrfH2 = U8_TO_QRFH2(temp_u8);
            hubQrfH2.isFM = 0;
            temp_u8 = QRF_TO_U8(hubQrfH2);
            setDevicQrfH2(rfmid, &temp_u8);
        }
#else
        temp_u8 = getThisQrfH1();
        QRFH1_t rfmQrfH1 = U8_TO_QRFH1(temp_u8);
        temp_u8 = getThisQrfH2();
        QRFH2_t rfmQrfH2 = U8_TO_QRFH2(temp_u8);
        rfmQrfH2.isFM = 0; // isFM 查询子设备关闭
        temp_u8 = QRF_TO_U8(rfmQrfH2);
        setThisQrfH2(&temp_u8); // isFM 查询子设备关闭
        SM_device_QRF_state_Handle(rfmQrfH1, rfmQrfH2);
        isUMPorcess();
        if (net_printf_log)
            printf("H2:%02X ", temp_u8);
#endif
    }
    break;
    case 0x03: // 表示进入Rssi信号强度模式，见QRF，6s心跳；
    {
#ifdef HUB_DEVICE
        for (uint8_t no = 0; no < len - 1; no++)
        {
            rfmid = data[pos + no];
            temp_u8 = getDevicQrfH2(rfmid);
            QRFH2_t hubQrfH2 = U8_TO_QRFH2(temp_u8);
            hubQrfH2.isRSSI = 1;
            temp_u8 = QRF_TO_U8(hubQrfH2);
            setDevicQrfH2(rfmid, &temp_u8);
        }
#else
        temp_u8 = getThisQrfH1();
        QRFH1_t rfmQrfH1 = U8_TO_QRFH1(temp_u8);
        temp_u8 = getThisQrfH2();
        QRFH2_t rfmQrfH2 = U8_TO_QRFH2(temp_u8);
        rfmQrfH2.isRSSI = 1;
        temp_u8 = QRF_TO_U8(rfmQrfH2);
        setThisQrfH2(&temp_u8);
        SM_device_QRF_state_Handle(rfmQrfH1, rfmQrfH2);
        isUMPorcess();
        if (net_printf_log)
            printf("H2:%02X ", temp_u8);
#endif
    }
    break;
    case 0x04: // 表示退出Rssi信号强度模式；
    {
#ifdef HUB_DEVICE
        for (uint8_t no = 0; no < len - 1; no++)
        {
            rfmid = data[pos + no];
            temp_u8 = getDevicQrfH2(rfmid);
            QRFH2_t hubQrfH2 = U8_TO_QRFH2(temp_u8);
            hubQrfH2.isRSSI = 0;
            temp_u8 = QRF_TO_U8(hubQrfH2);
            setDevicQrfH2(rfmid, &temp_u8);
        }
#else
        temp_u8 = getThisQrfH1();
        QRFH1_t rfmQrfH1 = U8_TO_QRFH1(temp_u8);
        temp_u8 = getThisQrfH2();
        QRFH2_t rfmQrfH2 = U8_TO_QRFH2(temp_u8);
        rfmQrfH2.isRSSI = 0;
        temp_u8 = QRF_TO_U8(rfmQrfH2);
        setThisQrfH2(&temp_u8);
        SM_device_QRF_state_Handle(rfmQrfH1, rfmQrfH2);
        isUMPorcess();
        if (net_printf_log)
            printf("H2:%02X ", temp_u8);
#endif
    }
    break;
    case 0xF0: // 开始固件广播升级，需上报升级请求物模型；
#ifdef HUB_DEVICE
        net.ota_flag = 1;
#else
        /*子设备处理*/
        consumption_deal_sync_broadcast_updateme_keyvalue(data + 1, len);
#endif
        break;
    case 0xF1: // 固件块校验请求；
#ifdef HUB_DEVICE
        net.ota_flag = 1;
#else
        /*子设备处理*/
        consumption_deal_file_updateme_keyvalue(data + 1, len);
#endif
        break;
    default:
        // need_ack = false;
        break;
    }
#if 0 // 取消单项广播 updateme使用双向广播应答机制
#ifdef RFM_DEVICE
    if (need_ack == true)
    {
        // 广播应答机制
        net.oneway[net.oneway_size++] = BTYPE_UPDATEME;
    }
#else
    net.oneway[net.oneway_size++] = BTYPE_UPDATEME;
#endif
#endif
}

/*
 * 广播物模型处理 hub/rfm共用
 * 输入： data      广播物模型数据
 *      dataSize   数据长度
 * 输出：处理结果
 */
bool net_BTypeData_process(uint8_t *data, uint16_t dataSize)
{
    // uint8_t ret = 0;
    uint8_t btype = 0;
    unpackBretryAckCtrl(net.bretryAckCtrl);
    if (net_printf_log)
        printf("N_BA:%02X ", net.bretryAckCtrl);

    net.oneway_size = 0;
    net.twoway_size = 0;
    net.bd_flag = 0;
    net.ota_flag = 0;
    for (uint16_t pos = 0; pos < dataSize;)
    {
        btype = data[pos];
        pos++;
        if (net_printf_log)
            printf("BT:%02X ", btype);
        switch (btype)
        {
        case BTYPE_NONE:
            return false;
            break;
        case BTYPE_IO_EN:
            save_ioen_from_bd(data + pos);
            net.oneway[net.oneway_size++] = BTYPE_IO_EN;
            pos += BTYPE_IO_EN_DATA_LEN;
            break;
        case BTYPE_SOUNDER:
        {
            if (net.bseq[0] != data[pos])
            {
                net.bseq[0] = data[pos];
                save_option(BTYPE_SOUNDER, data + pos + 1, 14); // 保存物模型
                net.twoway[net.twoway_size++] = BTYPE_SOUNDER;
                net.twoway[net.twoway_size++] = net.bseq[0];
                net.twoway[net.twoway_size++] = data[pos + 1];
                net.twoway[net.twoway_size++] = data[pos + 2];
            }
            pos += BTYPE_SOUNDER_DATA_LEN;
            break;
        }
        case BTYPE_KEYPAD:
            if (net.bseq[1] != data[pos])
            {
                net.bseq[1] = data[pos];
                save_option(BTYPE_KEYPAD, data + pos + 1, 9); // 保存物模型
                net.twoway[net.twoway_size++] = BTYPE_KEYPAD;
                net.twoway[net.twoway_size++] = net.bseq[1];
                net.twoway[net.twoway_size++] = data[pos + 1];
            }
            pos += BTYPE_KEYPAD_DATA_LEN;
            break;
        case BTYPE_SWITCH:
            if (net.bseq[2] != data[pos])
            {
                net.bseq[2] = data[pos];
                save_option(BTYPE_SWITCH, data + pos + 2, data[pos + 1]); // 保存物模型 len表示之后数据个数  TODO:BYTE2 BYTE3 如何计算数量
                net.twoway[net.twoway_size++] = BTYPE_SWITCH;
                net.twoway[net.twoway_size++] = net.bseq[2];
                // 双向广播带所有数据
                uint8_t size = data[pos + 1] + 1;
                memcpy(net.twoway + net.twoway_size, data + pos + 1, size);
                net.twoway_size += size;
            }
            pos += data[pos + 1] + 2;
            break;
        // case BTYPE_SOUNDER_CTRL:
        //  TODO
        //    break;
        // case BTYPE_KEYPAD_CTRL:
        //     // TODO
        //     break;
        // case BTYPE_SWITCH_CTRL:
        //     // TODO
        //     pos += data[pos] + 1;
        //     break;
        // case BTYPE_GROUP:
        //     // TODO
        //     pos += data[pos] + 1;
        //     break;
        case BTYPE_UPDATEME:
            BTypeUpdatemeProcess(data + pos);
            // 子设备双向广播处理
            net.twoway[net.twoway_size++] = BTYPE_UPDATEME;
            memcpy(net.twoway + net.twoway_size, data + pos, data[pos] + 1);
            net.twoway_size += data[pos] + 1;
            pos += data[pos] + 1;
            break;
        case BTYPE_GROUP_SET:
            // TODO
            pos += data[pos] + 1;
            break;
        default:
            pos += data[pos] + 1; // 新增广播物模型默认后面是len
            break;
        }
    }
    // 单双向广播应答机制
#ifdef HUB_DEVICE
    net.bd_flag = 1; // 需要广播
#else
    start_timer_to_trigger_twoway_response(net.twoway, net.twoway_size, &net.bd_flag);
    if (net_printf_log)
        APP_PRINTF_HEX("[BD]TW:", (uint8_t *)net.twoway, net.twoway_size);
#endif

    return true;
}

// 广播处理
void net_broadcasr_process(uint8_t *packet, RBFMacHeader_t hdr)
{
    RBFMacMessageGWBoardcast_t msg;
    RBF_gw_broadcast_payload_packetToMsg(packet, &msg);
    Log_rx(hdr, &msg);
    net_BTypeData_process(msg.bTypeData, msg.bTypeDataSize); // 广播内容处理
}

// 解包 返回值
bool net_unpack(uint8_t *packet, uint16_t packet_len)
{
    bool ret = false;
    RBFMacHeader_t hdr;
    // uint8_t _key[RBF_KEY_LENGTH_MAX] = {0};
    set_net_data_status(NET_DATA_STATUS_FAIL); // 初始进入默认解析失败
#ifdef RFM_DEVICE
    // 是否注册
    if (isregeist() == false)
    {
        if (net_printf_log)
            printf("NO Reg\r\n");
        return ret;
    }
#endif
    // 解析头
    if (RBF_header_parse(packet, packet_len, &hdr) != RBF_RET_STATUS_SUCCESS)
    {
#if (APP_LOG_LEVEL_FILTER_THRESHOLD == xAPP_LOG_LEVEL_ERROR)
        DS_app_log_error("rec no header!\r\n");
#endif
        return ret;
    }
#ifdef HUB_DEVICE
    if (hdr.srcId == ADDRESS_BROADCAST)
        return ret;
#endif
    // 地址判断 systemId 是否是同一网络
    if (net_addressing_check_sysId(hdr.panId) != true) // if (net_addressing_check_panId(hdr.panId) != true)
    {
#if ((APP_LOG_LEVEL_FILTER_THRESHOLD == APP_LOG_LEVEL_ERROR) || defined(CONFIG_LOG_NET_PACKET_ERROR))
        if (net_printf_log)
            DS_app_log_error("panId(0x%06X) rec(0x%06X) not match\r\n", (unsigned int)net.panId, (unsigned int)hdr.panId);
#endif
        return ret;
    }
// 地址判断destID是否是本地地址或广播
#ifdef RFM_DEVICE
    if (hdr.destID != net.rfmid && !(hdr.destID == ADDRESS_BROADCAST && hdr.srcId == ADDRESS_HUB)) // 子设备:只处理目的地址为自身，或者是HUB发出的广播
    {
#if ((APP_LOG_LEVEL_FILTER_THRESHOLD == APP_LOG_LEVEL_ERROR) || defined(CONFIG_LOG_NET_PACKET_ERROR))
        if (net_printf_log)
            DS_app_log_error("destID (0x%02X) not match!\r\n", hdr.destID);
#endif
        return ret;
    }
#else
    if (hdr.destID != ADDRESS_HUB && hdr.destID != ADDRESS_BROADCAST) // HUB:只处理目的地址为hub，或广播地址
    {
#if ((APP_LOG_LEVEL_FILTER_THRESHOLD == APP_LOG_LEVEL_ERROR) || defined(CONFIG_LOG_NET_PACKET_ERROR))
        if (net_printf_log)
            DS_app_log_error("destID (0x%02X) not match!\r\n", hdr.destID);
#endif
        return ret;
    }
#endif
    // 滚动码判断
    if (judge_revice_rolling_code(hdr.srcId, hdr.rollungCode) != ROLLING_CODE_MORE)
    {
#if ((APP_LOG_LEVEL_FILTER_THRESHOLD == APP_LOG_LEVEL_ERROR) || defined(CONFIG_LOG_NET_PACKET_ERROR))
        if (net_printf_log)
            DS_app_log_error("RC rec(0x%08X) not match\r\n", (unsigned int)hdr.rollungCode);
#endif
        return ret;
    }
    // 解密
    if (mac_payload_verify(packet) != SECURE_ELEMENT_SUCCESS)
    {
#if ((APP_LOG_LEVEL_FILTER_THRESHOLD == APP_LOG_LEVEL_ERROR) || defined(CONFIG_LOG_NET_PACKET_ERROR))
        if (net_printf_log)
            DS_app_log_error("verify fail\r\n");
#endif
        return ret;
    }

    // 收到有效报文
    save_device_recv_rolling_code(hdr.srcId, hdr.rollungCode);
#ifdef CONFIG_LOG_NET_PACKET
    if (net_printf_log)
        APP_PRINTF_HEX("verify_after:", packet, packet[RBF_MAC_PACKET_LEN_INDEX] + 1);
#endif
    net.rssi = (uint8_t)(bsp_rf_rssi_get() + 128);
    // 帧控制字
    unpack_frameCtl(hdr.frameCtl, &net.tpMode, &net.burstMode, &net.version);
    // payload 按cmd解析指令和处理
    switch (hdr.cmd) // RBF_CMD_TYPE
    {
#ifdef HUB_DEVICE
    case RBF_CMD_NODE_UPLOAD_EVENT:
    {
        net_ack.cmd = RBF_CMD_GATEWAY_ACK_EVENT; // 下一指令上报应答cmd
        net_upload_event_process(packet, hdr);
    }
    break;
    case RBF_CMD_NODE_UPLOAD_HEARTBEAT:
    {
        net_ack.cmd = RBF_CMD_GATEWAY_ACK_HEARTBEAT; // 下一指令心跳应答cmd
        net_upload_event_process(packet, hdr);
    }
    break;
#endif
#ifdef RFM_DEVICE
    case RBF_CMD_GATEWAY_ACK_EVENT:
    case RBF_CMD_GATEWAY_ACK_HEARTBEAT:
    {
        net_ack_upload_process(packet, hdr);
        isUMPorcess();
    }
    break;

    case RBF_CMD_GATEWAY_DOWNLOAD:
    {
        setMacTransEvent(EN_TRANS_REQ_ADHOC_SPVN_ACK, ADDRESS_HUB, ADHOC_RETRY_COUNT_MAX, LBT_REDO_COUNT_MAX); // 应答之
        RBFMacMessageGWDownload_t msg;
        RBF_gw_download_payload_packetToMsg(packet, &msg);

        setThisQrfH1(&msg.qrfH1);
        QRFH1_t hubQrfH1 = U8_TO_QRFH1(msg.qrfH1);
        setThisQrfH2(&msg.qrfH2);
        QRFH2_t hubQrfH2 = U8_TO_QRFH2(msg.qrfH2);

        SM_device_QRF_state_Handle(hubQrfH1, hubQrfH2);

        app_key_value_unpack(msg.keyValue, msg.keyValueSize);
        net_ack.cmd = RBF_CMD_NODE_ACK;
        set_cmd_ack(1);

        Log_rx(hdr, &msg);
        isUMPorcess();
    }
    break;
#else
    case RBF_CMD_NODE_ACK:
    {
        setMacTxStateEvent(EN_MAC_TX_EVENT_TYPE_WAIT_ACK_DONE, true); // 完成应答
        RBFMacMessageNodeAck_t msg;
        RBF_node_ack_payload_packetToMsg(packet, &msg);
        Log_rx(hdr, &msg);

        // uint8_t kv_input_output[3] = {APP_KEY_VALUE_ID_INPUT_OUTPUT, 0, 0};
        DS_hub_api_P2P_do_finish(hdr.srcId, DOWNLINK_RET_OK, msg.keyValue, msg.keyValueSize);
    }
    break;
#endif
#ifdef RFM_DEVICE
    case RBF_CMD_GATEWAY_SYNC_BROADCAST:
    {
        net_broadcasr_process(packet, hdr);
    }
    break;
    case RBF_CMD_GATEWAY_NOMAL_BROADCAST:
    {
        net_broadcasr_process(packet, hdr);
    }
    break;
#endif
    case RBF_CMD_NODE_ROAMING:
    {
        Log_RF();     // RF信息打印
        Log_hdr(hdr); // 打印报头信息
        if (net_printf_log)
            APP_PRINTF_HEX("packet:", packet, packet[0] + 1); // 打印负载
    }
    break;
#ifdef RFM_DEVICE
    case RBF_CMD_NODE_FILE_TRANSFER_BLOCK:
    {
        consumption_deal_file_payload(packet + RBF_MAC_HEADER_INDEX_CMD + 1,
                                      packet[0] - RBF_MAC_HEADER_INDEX_CMD - RBF_TAIL_LENGTH_MAX);
        Log_RF(); // RF信息打印
        if (net_printf_log)
            DS_app_log_error("RID:%02X dID:%02X PID:%06X RC:%08X CD:%02X Fid:%02X%02X\r\n",
                             hdr.srcId, hdr.destID, hdr.panId, (unsigned int)hdr.rollungCode, hdr.cmd, packet[16], packet[17]);
    }
    break;
    case RBF_CMD_NODE_FILE_CHECK_REQ:
    {
        net_broadcasr_process(packet, hdr);
    }
    break;
#endif
    default:
        Log_RF();     // RF信息打印
        Log_hdr(hdr); // 打印报头信息
        if (net_printf_log)
            DS_app_log_error("cmd (0x%02X) not support!\r\n", hdr.cmd);
        break;
    }

    set_net_data_status(NET_DATA_STATUS_SUCCESS); // 解析成功
    ret = true;
    return ret;
}
/*
 *
 * 注册过程报文合法性判断，正常网络层不调用此函数
 */
bool net_unpack_ack(uint8_t *packet, uint16_t packet_len)
{
    bool ret = false;
    RBFMacHeader_t hdr;
    uint8_t rfmid;
    uint32_t padid;
    getThisParam(ENpbyRfmId, &rfmid);
    getThisParam(ENpbyPanId, &padid);

    RBF_header_parse(packet, packet_len, &hdr);

#if 1
    if (net_addressing_check_sysId(hdr.panId) != true || hdr.panId == 0x00000)
    {
        DS_app_log_error("panId(0x%06X) rec(0x%06X) not match\r\n", (unsigned int)padid, (unsigned int)hdr.panId);
    }
#endif
    if (hdr.destID != rfmid)
    {
        //        #if ((APP_LOG_LEVEL_FILTER_THRESHOLD == APP_LOG_LEVEL_ERROR) || defined(CONFIG_LOG_NET_PACKET_ERROR))
        //        if (net_printf_log){
        DS_app_log_error("destID (0x%02X) not match!\r\n", hdr.destID);
        //        }
        //        #endif
        return ret;
    }
    //
    //

    ret = true;
    return ret;
}

// mac rx回调
bool mac_RxCallback(RF_PACKET_ST *pPacket, MAC_RX_STATE_E currState, void *pData)
{
    uint8_t *pPacketData = NULL;
    bool ret = true;
    pPacketData = pPacket->start_of_packet;

    if (false == net_unpack(pPacketData, pPacket->packet_size)) // 报文解析错误
    {
        if (net_printf_log)
            DS_app_log_error("*pid:%02X%02X%02X sid:%02X did:%02X rc:%02X%02X%02X%02X cd:%02X\r\n",
                             pPacketData[RBF_MAC_HEADER_INDEX_PANDID],
                             pPacketData[RBF_MAC_HEADER_INDEX_PANDID + 1],
                             pPacketData[RBF_MAC_HEADER_INDEX_PANDID + 2],
                             pPacketData[RBF_MAC_HEADER_INDEX_SRCID],
                             pPacketData[RBF_MAC_HEADER_INDEX_DESTID],
                             pPacketData[RBF_MAC_HEADER_INDEX_ROLLUNGCODE],
                             pPacketData[RBF_MAC_HEADER_INDEX_ROLLUNGCODE + 1],
                             pPacketData[RBF_MAC_HEADER_INDEX_ROLLUNGCODE + 2],
                             pPacketData[RBF_MAC_HEADER_INDEX_ROLLUNGCODE + 3],
                             pPacketData[RBF_MAC_HEADER_INDEX_CMD]);
    }
    (void)pData;
    (void)currState;
    return ret;
}
#ifdef RFM_DEVICE
// 上报物模型结果
netCallBackFun net_upload_result = NULL;
// 注册函数
int reg_net_upload_result(netCallBackFun p)
{
    net_upload_result = p;
    return 0;
}
#endif
// mac 上行回调
void mac_txStatecallbackAdhocUp(uint8_t **ppPacket, MAC_TX_STATE_E currState, void *pData)
{
    RETRY_CTRL_ST *pRetryCtrl = (RETRY_CTRL_ST *)pData;
#ifdef CONFIG_LOG_NET_PACKET
    if (net_printf_log)
        DS_app_log_debug("up cb state:%d\r\n", currState);
#endif
    // 回调状态为组包
    if (currState == EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE)
    {
        *ppPacket = packet_tx;
        if ((pRetryCtrl->byCrtlFlag & RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED) != RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED || // LBT成功
            (callback_type != EN_TRANS_REQ_ADHOC_UPLINK))                                                                // LBT失败且上次非本回调
        {
            net_pack_t net_pack_data = {
                .retry = pRetryCtrl->byRetryCount,
            };
            net_pack(ADDRESS_HUB, packet_tx, RBF_CMD_NODE_UPLOAD_EVENT, &net_pack_data);
            callback_type = EN_TRANS_REQ_ADHOC_UPLINK;
        }
#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
        {
            DS_app_log_debug("CMD[%d] destID[0x%02X]\n", packet_tx[RBF_MAC_HEADER_INDEX_CMD], packet_tx[RBF_MAC_HEADER_INDEX_DESTID]);
            APP_PRINTF_HEX("[up]", packet_tx, packet_tx[0] + 1);
        }
#endif
    }

    if (pData != NULL)
    {
#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
            DS_app_log_debug("up retry%d-%d\r\n", pRetryCtrl->byRetryCount, pRetryCtrl->byRetryMaxTimes);
#endif
    }

    if (currState == EN_MAC_TX_STATE_SUCCED)
    {
        net_msgseq_update();
#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
            DS_app_log_debug("up succeed\r\n");
#endif
#ifdef RFM_DEVICE
        if (net_upload_result != NULL)
        { // 上报成功
            net_upload_result(NET_UP_EVENT_ADHOC, true, getLastRecvPacketPoint()->details.rssi, net_upload_kv_buff);
        }
#endif
    }
    if (currState == EN_MAC_TX_STATE_FAILED)
    {
        net_msgseq_update();
        if (net_printf_log)
            DS_app_log_error("up failed\r\n");
#ifdef RFM_DEVICE
        if (net_upload_result != NULL)
        { // 上报失败
            net_upload_result(NET_UP_EVENT_ADHOC, false, -128, net_upload_kv_buff);
        }
#endif
    }
}

// mac 下行回调0
void mac_txStatecallbackAdhocDown0(uint8_t **ppPacket, MAC_TX_STATE_E currState, void *pData)
{
    RETRY_CTRL_ST *pRetryCtrl = (RETRY_CTRL_ST *)pData;
    *ppPacket = packet_tx;
#ifdef CONFIG_LOG_NET_PACKET
    DS_app_log_debug("dw1 cb state:%d\r\n", currState);
#endif
    if (currState == EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE)
    {
        if (((pRetryCtrl->byCrtlFlag & RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED) != RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED) || // LBT成功
            (callback_type != EN_TRANS_REQ_ADHOC_DOWNLINK_START))                                                          // LBT失败且上次非本回调
        {
            net_pack_t net_pack_data = {
                .p2p_ch = 0,
                .retry = pRetryCtrl->byRetryCount,
            };
            net_pack(net_p2p[0].destID, packet_tx, RBF_CMD_GATEWAY_DOWNLOAD, &net_pack_data);
            callback_type = EN_TRANS_REQ_ADHOC_DOWNLINK_START;
        }

#ifdef CONFIG_LOG_NET_PACKET
        DS_app_log_debug("cmd=%d\n", packet_tx[RBF_MAC_HEADER_INDEX_CMD]);
        APP_PRINTF_HEX("[dw0 tx]", packet_tx, packet_tx[0] + RBF_MAC_PACKET_LEN_SIZE);
#endif
    }
    if (pData != NULL)
    {
#ifdef CONFIG_LOG_NET_PACKET
        DS_app_log_error("dw0 retry%d-%d\r\n", pRetryCtrl->byRetryCount, pRetryCtrl->byRetryMaxTimes);
#endif
    }
    if (currState == EN_MAC_TX_STATE_SUCCED)
    {
        net_msgseq_update();
        net_p2p[0].destID = 0;
#ifdef CONFIG_LOG_NET_PACKET
        DS_app_log_debug("dw0 succeed\r\n");
#endif
    }
    if (currState == EN_MAC_TX_STATE_FAILED)
    {
        net_msgseq_update();
#ifdef HUB_DEVICE
        DS_hub_api_P2P_do_finish(net_p2p[0].destID, DOWNLINK_RET_COMM_FAIL, net_p2p[0].key_value, net_p2p[0].key_value_size); // 点对点操作失败测试
#endif
        net_p2p[0].destID = 0;
        DS_app_log_error("dw0 failed\r\n");
    }
}

// mac 下行回调1
void mac_txStatecallbackAdhocDown1(uint8_t **ppPacket, MAC_TX_STATE_E currState, void *pData)
{
    RETRY_CTRL_ST *pRetryCtrl = (RETRY_CTRL_ST *)pData;
    *ppPacket = packet_tx;
#ifdef CONFIG_LOG_NET_PACKET
    if (net_printf_log)
        DS_app_log_debug("dw1 cb state:%d\r\n", currState);
#endif
    if (currState == EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE)
    {
        if (((pRetryCtrl->byCrtlFlag & RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED) != RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED) || // LBT成功
            (callback_type != EN_TRANS_REQ_ADHOC_DOWNLINK_START + 1))                                                      // LBT失败且上次非本回调
        {
            net_pack_t net_pack_data = {
                .p2p_ch = 1,
                .retry = pRetryCtrl->byRetryCount,
            };
            net_pack(net_p2p[1].destID, packet_tx, RBF_CMD_GATEWAY_DOWNLOAD, &net_pack_data);
            callback_type = EN_TRANS_REQ_ADHOC_DOWNLINK_START + 1;
        }

#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
        {
            DS_app_log_debug("cmd=%d\n", packet_tx[RBF_MAC_HEADER_INDEX_CMD]);
            APP_PRINTF_HEX("[dw1 tx]", packet_tx, packet_tx[0] + RBF_MAC_PACKET_LEN_SIZE);
        }
#endif
    }
    if (pData != NULL)
    {
#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
            DS_app_log_error("dw1 retry%d-%d\r\n", pRetryCtrl->byRetryCount, pRetryCtrl->byRetryMaxTimes);
#endif
    }
    if (currState == EN_MAC_TX_STATE_SUCCED)
    {
        net_msgseq_update();
        net_p2p[1].destID = 0;
#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
            DS_app_log_debug("dw1 succeed\r\n");
#endif
    }
    if (currState == EN_MAC_TX_STATE_FAILED)
    {
        net_msgseq_update();
#ifdef HUB_DEVICE
        DS_hub_api_P2P_do_finish(net_p2p[1].destID, DOWNLINK_RET_COMM_FAIL, net_p2p[1].key_value, net_p2p[1].key_value_size); // 点对点操作失败测试
#endif
        net_p2p[1].destID = 0;
        DS_app_log_error("dw1 failed\r\n");
    }
}

// mac 下行回调2
void mac_txStatecallbackAdhocDown2(uint8_t **ppPacket, MAC_TX_STATE_E currState, void *pData)
{
    RETRY_CTRL_ST *pRetryCtrl = (RETRY_CTRL_ST *)pData;
    *ppPacket = packet_tx;
#ifdef CONFIG_LOG_NET_PACKET
    DS_app_log_debug("dw2 cb state:%d\r\n", currState);
#endif
    if (currState == EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE)
    {
        if (((pRetryCtrl->byCrtlFlag & RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED) != RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED) || // LBT成功
            (callback_type != EN_TRANS_REQ_ADHOC_DOWNLINK_START + 2))                                                      // LBT失败且上次非本回调
        {
            net_pack_t net_pack_data = {
                .p2p_ch = 2,
                .retry = pRetryCtrl->byRetryCount,
            };
            net_pack(net_p2p[2].destID, packet_tx, RBF_CMD_GATEWAY_DOWNLOAD, &net_pack_data);
            callback_type = EN_TRANS_REQ_ADHOC_DOWNLINK_START + 2;
        }

#ifdef CONFIG_LOG_NET_PACKET
        DS_app_log_debug("cmd=%d\n", packet_tx[RBF_MAC_HEADER_INDEX_CMD]);
        APP_PRINTF_HEX("[dw2 tx]", packet_tx, packet_tx[0] + RBF_MAC_PACKET_LEN_SIZE);
#endif
    }
    if (pData != NULL)
    {
#ifdef CONFIG_LOG_NET_PACKET
        DS_app_log_error("dw2 retry%d-%d\r\n", pRetryCtrl->byRetryCount, pRetryCtrl->byRetryMaxTimes);
#endif
    }
    if (currState == EN_MAC_TX_STATE_SUCCED)
    {
        net_msgseq_update();
        net_p2p[2].destID = 0;
#ifdef CONFIG_LOG_NET_PACKET
        DS_app_log_debug("dw2 succeed\r\n");
#endif
    }
    if (currState == EN_MAC_TX_STATE_FAILED)
    {
        net_msgseq_update();
#ifdef HUB_DEVICE
        DS_hub_api_P2P_do_finish(net_p2p[2].destID, DOWNLINK_RET_COMM_FAIL, net_p2p[2].key_value, net_p2p[2].key_value_size); // 点对点操作失败测试
#endif
        net_p2p[2].destID = 0;
        DS_app_log_error("dw2 failed\r\n");
    }
}

// mac 下行回调3
void mac_txStatecallbackAdhocDown3(uint8_t **ppPacket, MAC_TX_STATE_E currState, void *pData)
{
    RETRY_CTRL_ST *pRetryCtrl = (RETRY_CTRL_ST *)pData;
    *ppPacket = packet_tx;
#ifdef CONFIG_LOG_NET_PACKET
    DS_app_log_debug("dw3 cb state:%d\r\n", currState);
#endif
    if (currState == EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE)
    {
        if (((pRetryCtrl->byCrtlFlag & RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED) != RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED) || // LBT成功
            (callback_type != EN_TRANS_REQ_ADHOC_DOWNLINK_START + 3))                                                      // LBT失败且上次非本回调
        {
            net_pack_t net_pack_data = {
                .p2p_ch = 3,
                .retry = pRetryCtrl->byRetryCount,
            };
            net_pack(net_p2p[3].destID, packet_tx, RBF_CMD_GATEWAY_DOWNLOAD, &net_pack_data);
            callback_type = EN_TRANS_REQ_ADHOC_DOWNLINK_START + 3;
        }

#ifdef CONFIG_LOG_NET_PACKET
        DS_app_log_debug("cmd=%d\n", packet_tx[RBF_MAC_HEADER_INDEX_CMD]);
        APP_PRINTF_HEX("[dw3 tx]", packet_tx, packet_tx[0] + RBF_MAC_PACKET_LEN_SIZE);
#endif
    }
    if (pData != NULL)
    {
#ifdef CONFIG_LOG_NET_PACKET
        DS_app_log_error("dw3 retry%d-%d\r\n", pRetryCtrl->byRetryCount, pRetryCtrl->byRetryMaxTimes);
#endif
    }
    if (currState == EN_MAC_TX_STATE_SUCCED)
    {
        net_msgseq_update();
        net_p2p[3].destID = 0;
#ifdef CONFIG_LOG_NET_PACKET
        DS_app_log_debug("dw3 succeed\r\n");
#endif
    }
    if (currState == EN_MAC_TX_STATE_FAILED)
    {
        net_msgseq_update();
#ifdef HUB_DEVICE
        DS_hub_api_P2P_do_finish(net_p2p[3].destID, DOWNLINK_RET_COMM_FAIL, net_p2p[3].key_value, net_p2p[3].key_value_size); // 点对点操作失败测试
#endif
        net_p2p[3].destID = 0;
        DS_app_log_error("dw3 failed\r\n");
    }
}

// mac 下行回调4
void mac_txStatecallbackAdhocDown4(uint8_t **ppPacket, MAC_TX_STATE_E currState, void *pData)
{
    RETRY_CTRL_ST *pRetryCtrl = (RETRY_CTRL_ST *)pData;
    *ppPacket = packet_tx;
#ifdef CONFIG_LOG_NET_PACKET
    DS_app_log_debug("dw4 cb state:%d\r\n", currState);
#endif
    if (currState == EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE)
    {
        if (((pRetryCtrl->byCrtlFlag & RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED) != RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED) || // LBT成功
            (callback_type != EN_TRANS_REQ_ADHOC_DOWNLINK_START + 4))                                                      // LBT失败且上次非本回调
        {
            net_pack_t net_pack_data = {
                .p2p_ch = 4,
                .retry = pRetryCtrl->byRetryCount,
            };
            net_pack(net_p2p[4].destID, packet_tx, RBF_CMD_GATEWAY_DOWNLOAD, &net_pack_data);
            callback_type = EN_TRANS_REQ_ADHOC_DOWNLINK_START + 4;
        }

#ifdef CONFIG_LOG_NET_PACKET
        DS_app_log_debug("cmd=%d\n", packet_tx[RBF_MAC_HEADER_INDEX_CMD]);
        APP_PRINTF_HEX("[dw4 tx]", packet_tx, packet_tx[0] + RBF_MAC_PACKET_LEN_SIZE);
#endif
    }
    if (pData != NULL)
    {
#ifdef CONFIG_LOG_NET_PACKET
        DS_app_log_error("dw4 retry%d-%d\r\n", pRetryCtrl->byRetryCount, pRetryCtrl->byRetryMaxTimes);
#endif
    }
    if (currState == EN_MAC_TX_STATE_SUCCED)
    {
        net_msgseq_update();
        net_p2p[4].destID = 0;
#ifdef CONFIG_LOG_NET_PACKET
        DS_app_log_debug("dw4 succeed\r\n");
#endif
    }
    if (currState == EN_MAC_TX_STATE_FAILED)
    {
        net_msgseq_update();
#ifdef HUB_DEVICE
        DS_hub_api_P2P_do_finish(net_p2p[4].destID, DOWNLINK_RET_COMM_FAIL, net_p2p[4].key_value, net_p2p[4].key_value_size); // 点对点操作失败测试
#endif
        net_p2p[4].destID = 0;
        DS_app_log_error("dw4 failed\r\n");
    }
}

// ack应答
void mac_txStatecallbackAck(uint8_t **ppPacket, MAC_TX_STATE_E currState, void *pData)
{
    // RETRY_CTRL_ST *pRetryCtrl = (RETRY_CTRL_ST *)pData;
#ifdef CONFIG_LOG_NET_PACKET
    if (net_printf_log)
        DS_app_log_debug("ack:%d\r\n", currState);
#endif
    //  回调状态为组包
    if (currState == EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE)
    {
        if (net_ack.cmd == RBF_CMD_GATEWAY_ACK_EVENT ||
            net_ack.cmd == RBF_CMD_GATEWAY_ACK_HEARTBEAT)
        {
            *ppPacket = packet_tx;
            net_pack(net_ack.destID, packet_tx, net_ack.cmd, NULL);
        }
        else if (net_ack.cmd == RBF_CMD_NODE_ACK)
        {
            *ppPacket = packet_tx;
            net_pack(ADDRESS_HUB, packet_tx, net_ack.cmd, NULL);
        }
        else
        { // 确保应答cmd正确
            DS_app_log_debug("[ack]:cmd(%02X) error", net_ack.cmd);
        }

#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
        {
            DS_app_log_debug("cmd=%d\n", packet_tx[RBF_MAC_HEADER_INDEX_CMD]);
            APP_PRINTF_HEX("[ack] :", packet_tx, packet_tx[0] + RBF_MAC_PACKET_LEN_SIZE);
        }
#endif
        callback_type = EN_TRANS_REQ_ADHOC_SPVN_ACK;
    }

    if (pData != NULL)
    {
#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
            DS_app_log_debug("ack retry%d-%d\r\n", pRetryCtrl->byRetryCount, pRetryCtrl->byRetryMaxTimes);
#endif
    }
    if (currState == EN_MAC_TX_STATE_SUCCED)
    {
#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
            DS_app_log_debug("ack succeed\r\n");
#endif
    }
    if (currState == EN_MAC_TX_STATE_FAILED)
    {
        if (net_printf_log)
            DS_app_log_error("ack failed\r\n");
    }
}

// 心跳回调
void mac_txStatecallbackAdhocSpvn(uint8_t **ppPacket, MAC_TX_STATE_E currState, void *pData)
{
#ifdef RFM_DEVICE
    RETRY_CTRL_ST *pRetryCtrl = (RETRY_CTRL_ST *)pData;
#ifdef CONFIG_LOG_NET_PACKET
    if (net_printf_log)
        DS_app_log_debug("Spvn:%d\r\n", currState);
#endif
    //  回调状态为组包
    if (currState == EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE && isregeist())
    {
        *ppPacket = packet_tx;
        if ((pRetryCtrl->byCrtlFlag & RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED) != RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED || // LBT成功
            (callback_type != EN_TRANS_REQ_SPVN))                                                                        // LBT失败且上次非本回调
        {
            net_pack_t net_pack_data = {
                .retry = pRetryCtrl->byRetryCount,
            };
            net_pack(ADDRESS_HUB, packet_tx, RBF_CMD_NODE_UPLOAD_HEARTBEAT, &net_pack_data);
            callback_type = EN_TRANS_REQ_SPVN;
        }
#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
        {
            DS_app_log_debug("cmd=%d\n", packet_tx[RBF_MAC_HEADER_INDEX_CMD]);
            APP_PRINTF_HEX("[Spvn] :", packet_tx, packet_tx[0] + RBF_MAC_PACKET_LEN_SIZE);
        }
#endif
    }

    if (pData != NULL)
    {
        if (net_printf_log)
            DS_app_log_error("Spvn retry%d-%d\r\n", pRetryCtrl->byRetryCount, pRetryCtrl->byRetryMaxTimes);
    }

    if (currState == EN_MAC_TX_STATE_SUCCED)
    {
        net_msgseq_update();

        if (net_upload_result != NULL)
        { // 上报成功
            net_upload_result(NET_UP_EVENT_SPVN, true, getLastRecvPacketPoint()->details.rssi, NULL);
        }
#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
            DS_app_log_debug("Spvn succeed\r\n");
#endif
    }

    if (currState == EN_MAC_TX_STATE_FAILED)
    {
        if (EN_TRANS_REQ_SPVN == pRetryCtrl->byEventType && 0 == pRetryCtrl->byRetryMaxTimes)
        {
            uint8_t temp_u8 = getThisQrfH2();
            QRFH2_t rfmQrfH2 = U8_TO_QRFH2(temp_u8);
            if (rfmQrfH2.isRSSI) // 处于RSSI模式时，若心跳交互失败，提示信号指示失败
            {
                rssiCheckFailedIndicate();
            }

            if (net_upload_result != NULL)
            { // 上报失败
                net_upload_result(NET_UP_EVENT_SPVN, false, -128, NULL);
            }

            if (net_printf_log)
                DS_app_log_error("Spvn failed\r\n");
        }
        else
        {
            if (net_printf_log)
                DS_app_log_error("Spvn interrupted\r\n");
        }

        net_msgseq_update();
    }
#else
    (void)ppPacket;
    (void)currState;
    (void)pData;
#endif
}

// 同步广播回调
void mac_txStatecallbackBcast(uint8_t **ppPacket, MAC_TX_STATE_E currState, void *pData)
{
#ifdef HUB_DEVICE
    // RETRY_CTRL_ST *pRetryCtrl = (RETRY_CTRL_ST *)pData;
#ifdef CONFIG_LOG_NET_PACKET
    if (net_printf_log)
        DS_app_log_debug("SYBC:%d\r\n", currState);
#endif
    //  回调状态为组包
    if (currState == EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE)
    {
        if (net.bd_flag) // 广播标志
        {
            net.bd_flag = 0; // 广播标志
            *ppPacket = packet_tx;
            net.bretryAckCtrl = GET_BRETRYACKCTRL(net.bretryCount, net.ackCtrl);
            net_pack(ADDRESS_BROADCAST, packet_tx, RBF_CMD_GATEWAY_SYNC_BROADCAST, NULL);
            // 广播retry机制
            if (net_printf_log)
            {
                DS_app_log_error("[BD]FG:%02X CN:%02X MX:%02X\r\n", net.bd_flag, net.bretryCount, net.bretry);
                APP_PRINTF_HEX("[BD]OW:", (uint8_t *)net.oneway, net.oneway_size);
                APP_PRINTF_HEX("[BD]TW:", (uint8_t *)net.twoway, net.twoway_size);
            }
            start_timer_to_trigger_broadcast_retry(net.oneway, net.oneway_size,
                                                   net.twoway, net.twoway_size,
                                                   &net.bretryCount, net.bretry,
                                                   &net.bd_flag, net.ota_flag);
#ifdef CONFIG_LOG_NET_PACKET
            if (net_printf_log)
            {
                DS_app_log_debug("cmd=%d\n", packet_tx[RBF_MAC_HEADER_INDEX_CMD]);
                APP_PRINTF_HEX("[SYBC] :", packet_tx, packet_tx[0] + RBF_MAC_PACKET_LEN_SIZE);
            }
#endif
        }
        else
            *ppPacket = NULL;
    }
    if (pData != NULL)
    {
#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
            DS_app_log_debug("SYBC retry%d-%d\r\n", net.bretryCount, net.bretry);
#endif
    }
    if (currState == EN_MAC_TX_STATE_SUCCED)
    {
        net_msgseq_update();
#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
            DS_app_log_debug("SYBC succeed\r\n");
#endif
    }
    if (currState == EN_MAC_TX_STATE_FAILED)
    {
        net_msgseq_update();
        if (net_printf_log)
            DS_app_log_error("SYBC failed\r\n");
    }

#else
    (void)ppPacket;
    (void)currState;
    (void)pData;
#endif
}

// 普通广播回调 长供电 继电器、插座灯
void mac_txStatecallbackRealTimeBcast(uint8_t **ppPacket, MAC_TX_STATE_E currState, void *pData)
{
#ifdef HUB_DEVICE
    // RETRY_CTRL_ST *pRetryCtrl = (RETRY_CTRL_ST *)pData;
#ifdef CONFIG_LOG_NET_PACKET
    if (net_printf_log)
        DS_app_log_debug("RTBC:%d\r\n", currState);
#endif
    //  回调状态为组包
    if (currState == EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE)
    {
        if (net.bd_flag) // 广播标志
        {
            net.bd_flag = 0; // 广播标志
            *ppPacket = packet_tx;
            net.bretryAckCtrl = GET_BRETRYACKCTRL(net.bretryCount, net.ackCtrl);
            net_pack(ADDRESS_BROADCAST, packet_tx, RBF_CMD_GATEWAY_NOMAL_BROADCAST, NULL);
            // 广播retry机制
            if (net_printf_log)
            {
                DS_app_log_error("[BD]FG:%02X CN:%02X MX:%02X\r\n", net.bd_flag, net.bretryCount, net.bretry);
                APP_PRINTF_HEX("[BD]OW:", (uint8_t *)net.oneway, net.oneway_size);
                APP_PRINTF_HEX("[BD]TW:", (uint8_t *)net.twoway, net.twoway_size);
            }
            start_timer_to_trigger_broadcast_retry(net.oneway, net.oneway_size,
                                                   net.twoway, net.twoway_size,
                                                   &net.bretryCount, net.bretry,
                                                   &net.bd_flag, net.ota_flag);

#ifdef CONFIG_LOG_NET_PACKET
            if (net_printf_log)
            {
                DS_app_log_debug("cmd=%d\n", packet_tx[RBF_MAC_HEADER_INDEX_CMD]);
                APP_PRINTF_HEX("[RTBC] :", packet_tx, packet_tx[0] + RBF_MAC_PACKET_LEN_SIZE);
            }
#endif
        }
        else
            *ppPacket = packet_tx;
    }
    if (pData != NULL)
    {
        if (net_printf_log)
            DS_app_log_error("RTBC RT%d-%d\r\n", net.bretryCount, net.bretry);
    }
    if (currState == EN_MAC_TX_STATE_SUCCED)
    {
        net_msgseq_update();
#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
            DS_app_log_debug("RTBC S\r\n");
#endif
    }
    if (currState == EN_MAC_TX_STATE_FAILED)
    {
        net_msgseq_update();
        if (net_printf_log)
            DS_app_log_error("RTBC F\r\n");
    }
#else
    (void)ppPacket;
    (void)currState;
    (void)pData;
#endif
}

void set_packet_payload(uint8_t cmd, uint8_t *payload, uint16_t payload_size)
{
#if defined(CONFIG_LOG_RBFBROADCAST)
    if (broadcast_data == NULL)
    {
#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
            DS_app_log_debug("no broadcast payload!(cmd=%d)\r\n", cmd);
#endif
    }

#else
    (void)cmd;
    (void)payload;
    (void)payload_size;
#endif
}

void rfm_net_process()
{
    if (buff_key_value_up.count == 0 && net.bd_flag == 0) // 无物模型 && 无需上报广播应答
    {
        // DS_app_log_debug("no key value!\r\n");
        return;
    }
    else
    {
        if (checkMacTransEvent(EN_TRANS_REQ_ADHOC_UPLINK) != 0) // 不空闲
            return;

        // 获取物模型
        // printf("bd_flag:%d ", net.bd_flag);
        if (net.bd_flag == 1) // 上报广播应答 网络层物模型置顶（RFM上行）
        {
            net.bd_flag = 0;
            net_upload_kv_size = 0;
            // rfm组广播应答物模型
            memcpy(net_upload_kv_buff, broadcast_data, broadcast_data_size);                   // 广播应答物模型0x2F置顶
            app_key_value_pack(net_upload_kv_buff + broadcast_data_size, &net_upload_kv_size); // 获取上报物模型队列内的数据
            net_upload_kv_size += broadcast_data_size;
            if (net_printf_log)
            {
                printf("BD_ACK(%d)\r\n", broadcast_data_size);
                APP_PRINTF_HEX("bd:", broadcast_data, broadcast_data_size);
            }
            net_upload_kv_size += get_device_state(net_upload_kv_buff + net_upload_kv_size); // 获取上报设备状态物模型
            broadcast_data_size = 0;
        }
        else
        {
            #ifdef TEST_PRESS_KV  // 测试代码压大量物模型
            // keyValue_t keyValue = {
            //     .id = APP_KEY_VALUE_ID_INPUT_OUTPUT,
            //     .valueSize = APP_KEY_VALUE_INPUT_OUTPUT_SIZE,
            //     .value = {0x11, 0x11},
            // };
            // for (int i = 0; i < 100; i++)
            // {
            //     set_key_value(&keyValue);
            //     //printf("kv:%d ret:%d\r\n", i, set_key_value(&keyValue));
            // }
            #endif
            app_key_value_pack(net_upload_kv_buff, &net_upload_kv_size); // 获取上报物模型队列内的数据

            // printf("kv(%d):", net_upload_kv_size);
        }
        // TODO:解析键盘遥控器物模型是否保活(net_unpack_kv函数删除) 如有广播应答物模型先偏移地址
        // debug_printf_hex(net_upload_kv_buff, net_upload_kv_size);
        if (net_printf_log)
        {
            DS_app_log_debug("up(%d)\r\n", net_upload_kv_size);
            APP_PRINTF_HEX("kv ", net_upload_kv_buff, net_upload_kv_size);
        }
    }
    setMacTransEvent(EN_TRANS_REQ_ADHOC_UPLINK, ADDRESS_HUB, ADHOC_RETRY_COUNT_MAX, LBT_REDO_COUNT_MAX);
}

#ifdef RFM_DEVICE
bool isregeist(void) // true表示 已注册
{
    if (getThisParam(ENpbyRfmId, &net.rfmid) == 0) // 是否有注册地址
    {
        if (net.rfmid == 0)
        {
            return false;
        }
        return true;
    }
    else
    {
        return false;
    }
}
#endif
void net_init(void)
{
    get_net_printf_log();
    net_param_init(); // 参数初始化
}

void net_while(void)
{
#ifdef RFM_DEVICE

    if (isregeist() == true) // 循环获取注册状态
    {
        rfm_net_process();
    }
    else
    { // 未注册
        if (is_buff_key_value_up_empty() != true)
        { // 上报队列不为空时，清空队列
          // buff_key_value_up.count = 0; // 待验证

            uint8_t temp_buff[DATA_LINK_LENGTH] = {0};
            uint16_t temp_size = 0;
            app_key_value_pack(temp_buff, &temp_size);
            temp_size = 0;
        }
    }
#endif
#ifdef HUB_DEVICE
    // hub_net_process();
#endif
}
#ifdef HUB_DEVICE
void net_to_hub_event(uint8_t *packet, uint16_t packetLen)
{
    uint8_t rssi = 0;
    RBFMacHeader_t hdr;
    RBF_header_parse(packet, packetLen, &hdr);

    uint8_t *payload = packet + RBF_MAC_PACKET_LEN_SIZE + RBF_HEADER_LENGTH_MAX;
    uint8_t payload_len = packet[RBF_MAC_PACKET_LEN_INDEX] - RBF_MAC_HEADER_LEN - RBF_TAIL_LENGTH_MAX;
    unsigned char dbginfo[2] = {0};
    rssi = net.rssi;

    switch (hdr.cmd) // 节点上行
    {
    case RBF_CMD_NODE_PAGING:
        // payload_len-=KEY_MAX_LENGTH;//key_len
        return;
        break;
    case RBF_CMD_NODE_JOIN_CONFIRM:
#ifdef CONFIG_LOG_NET_PACKET
        if (net_printf_log)
            DS_app_log_debug("DeviceType:0x%02X\r\n", packet[RBF_MAC_PAYLOAD_JOIN_REQ_INDEX_DEVICETYPE]);
#endif
        break;
    case RBF_CMD_NODE_UPLOAD_EVENT:
        if (get_rec_node_msgseq(hdr.srcId) == packet[RBF_MAC_PAYLOAD_NODE_UPLOAD_EVENT_INDEX_MSGSEQ])
        {
            return; // aseq与上次相同，不向panel发送消息
        }
        break;
    case RBF_CMD_NODE_UPLOAD_HEARTBEAT:
    case RBF_CMD_NODE_ROAMING:
        break;
    case RBF_CMD_NODE_ACK:
        break;
    default:
        return;
        break;
    }
    // 保存节点msgseq
    set_rec_node_msgseq(hdr.srcId, packet[RBF_MAC_PAYLOAD_NODE_UPLOAD_EVENT_INDEX_MSGSEQ]);
#ifdef CONFIG_LOG_NET_PACKET
    if (net_printf_log)
    {
        DS_app_log_error("srcId :%02x, cmd %02x \r\n", hdr.srcId, hdr.cmd);
        DS_app_log_hexdump_error("[rfm payload]:", payload, payload_len);
    }
#endif
    DS_hub_api_creat_rfm_event(hdr.srcId,
                               (uint8_t *)&packet[RBF_MAC_HEADER_INDEX_ROLLUNGCODE],
                               rssi,
                               dbginfo,
                               hdr.cmd,
                               payload,
                               payload_len);
}
#endif
// 保存物模型 CAT_SOUNDER\CAT_KEYPAD\BTYPE_SWITCH
void save_option(uint8_t btype, uint8_t *bdata, uint8_t len)
{
    uint8_t option_data[3] = {0};      // byte1 byte3 TODO 以后要使用掩码，目前等于0
    uint8_t operate_data[1 + 3] = {0}; // 操作物模型 0字节为seq，协议栈内部使用，注意插座默认0会解除童锁
    uint8_t BcastValue = 0;
    uint8_t temp8 = 0;
    uint8_t *bitMask = bdata;
    uint8_t *option;
    uint8_t bitMaskSize = 0;
    CAT_TYPE_E cat;
    uint8_t no = 0;
    uint8_t rfmid = 0;
    if (btype == BTYPE_SOUNDER)
    {
        bitMaskSize = 2;
        cat = CAT_SOUNDER;
    }
    else if (btype == BTYPE_KEYPAD)
    {
        bitMaskSize = 1;
        cat = CAT_KEYPAD;
    }
    else if (btype == BTYPE_SWITCH)
        cat = CAT_IO;
    else
        return;
    option = bdata + bitMaskSize;
    for (uint8_t pos = 0; pos < len; no++) // pos可能加1，可能+2
    {
        if (((bitMask[pos / 8] >> (pos % 8) & 0x01)) || (bitMaskSize == 0)) // bitmask 2字节或0字节进入处理
        {
            if (btype == BTYPE_SWITCH) // switc使用no字段
                no = option[pos++];
            rfmid = get_rfmid_from_catno(cat, no);
#ifdef HUB_DEVICE
            // 解析出nodeId后 获取外设管理表内 历史Option字段 option
            getDeviceParam(rfmid, ENpbyNodeOptionFirst, option_data);
            if (net_printf_log)
                APP_PRINTF("get rid[%02X]=%02X OP:%02X %02X %02X\r\n", no, rfmid, option_data[0], option_data[1], option_data[2]);
#else
            // 子设备先读取option operate
            getThisParam(ENpbyOption, option_data);
#endif
            BcastValue = option[pos++];
            if (btype == BTYPE_SWITCH)
            {
                // 若BIT 0、1 不为0，表示Option物模型需更新
                if ((BcastValue & 0x03) != 0)
                {
                    option_data[1] = BcastValue & 0x03;
                }

                if ((BcastValue & 0xFC) != 0)
                {
                    operate_data[1 + 0] = (BcastValue & 0xFC) >> 2;
                    // 若OpreatData0 表示自动计时，则广播负载的第2个字节表示延时时间；
                    if (operate_data[1 + 0] == 4 || operate_data[1 + 0] == 5)
                        operate_data[1 + 1] = option[pos++];
                    //
                }
            }
            else if (btype == BTYPE_SOUNDER)
            {
                // BIT 0-4 Option物模型更新字段
                option_data[1] = BcastValue & 0x1F;

                operate_data[1 + 0] = (BcastValue & 0xE0) >> 5;
                // 若OpreatData0 表示自动计时，则广播负载的第2个字节表示延时时间；
                if (operate_data[1 + 0] == 7)
                    operate_data[1 + 1] = option[pos++];
                //
            }
            else if (btype == BTYPE_KEYPAD)
            {
                // BIT 0-3 Option物模型更新字段
                temp8 = BcastValue & 0x0F;
                if (temp8 < 10)
                {
                    option_data[1] = BcastValue;
                }
                else
                {
                    // Option2 在短暂操作后恢复上一次状态
                    if (temp8 == 10 || temp8 == 11 || temp8 == 14)
                    {
                        option_data[1] = (option_data[1] & 0x0F) | (BcastValue & 0xF0);
                    }
                    // option2 在短暂操作完后保持关闭
                    else
                    {
                        option_data[1] = (BcastValue & 0xF0);
                    }
                    operate_data[1 + 0] = (BcastValue & 0x0F);
                }
            }
            else
                continue;
#ifdef HUB_DEVICE
            setDeviceParam(rfmid, ENpbyNodeOptionFirst, option_data);
            if (net_printf_log)
                APP_PRINTF("set rid[%02X]=%02X OP:%02X %02X %02X\r\n", no, rfmid, option_data[0], option_data[1], option_data[2]);
#else
            if (net.rfmid == rfmid)
            {
                net.btype = btype;
                // option物模型
                uint8_t kv_size = 0;
                uint8_t kv_buf[OPTION_LENGTH + OPERATECTRL_LENGTH + 2] = {0};
                kv_buf[kv_size++] = APP_KEY_VALUE_ID_OPTION;
                memcpy(kv_buf + kv_size, option_data, OPTION_LENGTH);
                kv_size += OPTION_LENGTH;
                // operate物模型
                kv_buf[kv_size++] = APP_KEY_VALUE_ID_OPERATE_CTRL;
                memcpy(kv_buf + kv_size, operate_data, OPERATECTRL_LENGTH);
                kv_size += OPERATECTRL_LENGTH;
                // 压物模型
                app_key_value_unpack(kv_buf, kv_size);
                if (net_printf_log)
                {
                    printf("k-v:%02X(%d):", kv_buf[0], kv_size);
                    APP_PRINTF_HEX("", kv_buf, kv_size);
                    APP_PRINTF("rid[%02X]=%02X OP:%02X %02X %02X\r\n", no, rfmid, option_data[0], option_data[1], option_data[2]);
                }
            }
#endif
        }
        else
            pos++;
    }
}

// hub向net发送事件的处理
void hub_to_net_event(uint8_t *payload, uint16_t payloadLen)
{
#ifdef HUB_DEVICE
    uint8_t cmd = payload[1];
    // uint8_t pos = 0;
    uint8_t destID = 0;
    uint8_t p2p_key_value_buff[DATA_LINK_LENGTH] = {0};
    uint8_t p2p_key_value_size = 0;

    switch (cmd)
    {
    case RBF_CMD_GATEWAY_DOWNLOAD: // 主动下发 payload:[len] [cmd] [rfmid] [key value]
        destID = payload[2];
        p2p_key_value_size = payloadLen - 3;
        memcpy(p2p_key_value_buff, payload + 3, p2p_key_value_size);
#if 1
        if (net_printf_log)
        {
            DS_app_log_error("id %02X P2P_kv[%d]:", destID, p2p_key_value_size);
            APP_PRINTF_HEX("", p2p_key_value_buff, p2p_key_value_size);
        }
#endif
        // 当前设备是否有下行指令正在进行
        for (uint8_t index = 0; index < DOWNLINK_CONCURRENCY_CAPABILITY; index++)
        {
            if (net_p2p[index].destID == destID) // 当前设备存在下行指令
            {
                printf("DLCH[%d] EXIST ID[%02X]\r\n", index, destID);
                DS_hub_api_P2P_do_finish(destID, DOWNLINK_RET_EXIST, p2p_key_value_buff, p2p_key_value_size); // 错误返回
                return;
            }
        }

        for (uint8_t index = 0; index < DOWNLINK_CONCURRENCY_CAPABILITY; index++) // downlink 多通道检查 1~DOWNLINK_CONCURRENCY_CAPABILITY
        {
            TRANS_REQ_E downLinkCh = EN_TRANS_REQ_ADHOC_DOWNLINK_START + index; // mac点对点发送回调
            if (checkMacTransEvent(downLinkCh) == 0)                            // 当前通道空闲
            {
                net_p2p[index].destID = destID;
                printf("DLCH:%02X Set ID:%02X\r\n", index, net_p2p[index].destID);
                net_p2p[index].key_value_size = payloadLen - 3;
                memcpy(net_p2p[index].key_value, p2p_key_value_buff, net_p2p[index].key_value_size);
                setMacTransEvent(downLinkCh, net_p2p[index].destID, ADHOC_RETRY_COUNT_MAX, LBT_REDO_COUNT_MAX);
                return;
            }
        }
        printf("DLCH ALL BUSY\r\n");
        DS_hub_api_P2P_do_finish(destID, DOWNLINK_RET_CH_BUSY, p2p_key_value_buff, p2p_key_value_size); // 返回通道忙
        break;
    case RBF_CMD_GATEWAY_SYNC_BROADCAST:  // 同步广播 警号/
    case RBF_CMD_GATEWAY_NOMAL_BROADCAST: // 普通广播 无BSeq 继电器
        net.bretryAckCtrl = payload[2];
        net.bretryCount = 0;
        broadcast_data_size = payload[0] - 2;
        memcpy(broadcast_data, payload + 3, broadcast_data_size);
        if (net_printf_log)
            APP_PRINTF_HEX("broadcast_data:", broadcast_data, broadcast_data_size);

        net_BTypeData_process(broadcast_data, broadcast_data_size);

        break;
    default:
        break;
    }
#else
    (void)payload;
    (void)payloadLen;
#endif
}

// 产生广播物模型
app_key_value_err_e set_BD_key_value(const keyValue_t *keyValue)
{
    uint8_t pos = 0;
    if (net_printf_log)
        APP_PRINTF_HEX("BD kv:", (uint8_t *)keyValue->value, keyValue->valueSize);
    broadcast_data[pos++] = keyValue->id;
    memcpy(broadcast_data + pos, keyValue->value, keyValue->valueSize); // Len+(Btype+Bseq)[N]
    broadcast_data_size = pos + keyValue->valueSize;
    if (net_printf_log)
        APP_PRINTF_HEX("set BD kv:", broadcast_data, broadcast_data_size);
    return true;
}

// 获取广播物模型
app_key_value_err_e get_BD_key_value(keyValue_t *keyValue)
{
    uint8_t pos = 0;
    if (broadcast_data_size == 0)
        return APP_KEY_VALUE_ERR_NO_DATA;
    else
    {
        keyValue->id = broadcast_data[pos++];
        keyValue->valueSize = broadcast_data[pos];
        memcpy(keyValue->value, broadcast_data + pos, keyValue->valueSize); // Len+(Btype+Bseq)[N]
    }
    broadcast_data_size = 0; ///
    return true;
}

// 设备强制保活
void set_s_updateMeAppEn(bool state)
{
    s_updateMeAppEn = state;
}

// 打印开关
void set_net_printf_log(bool sw, bool save)
{
    net_printf_log = sw;
    if (save)
    {
        set_api_log_enable(NET_API_LOG, net_printf_log);
    }
}
// 获取开关状态
bool get_net_printf_log(void)
{
    get_api_log_enable(NET_API_LOG, &net_printf_log);
    return net_printf_log;
}
